Send a binary file (line by line) to a socket server with Netcat
After a lot of trying and pulling my hair I finally figured out that I could use NCat instead of Netcat as NCat can execute a command.
Start a connection with NCat to my socket server on port 5000
and execute the script ./sendlines.sh
:
ncat --exec "./sendlines.sh" 192.168.1.10 5000
./sendlines.sh
will send 4 lines with a delay of two seconds between each line:
#!/bin/bash
#
# sendlines.sh, v1.00, initial release
#
i="0"
while [ $i -lt 4 ]
do
echo -ne "\x00e\x00\x0000370513,6598,no,8,,2z\x00"
sleep 2
i=$[$i+1]
done
I have not figured out how to send a binary file, line by line, but this is not strictly necessary as I can manage by sending the same string many times.
If you know a way to send a binary file, line by line, it would be great as it would be the best solution for me.
How do you echo binary data to a listening C program via netcat?
I think the main problem is not with your code but with how you call netcat. When I run your server and use nc -u localhost 60000
, I can reproduce your problem: The server is blocking indefinitely without receiving data. However when I force netcat to use IPv4, I can send data to the server successfully:
nc -4 -u localhost 60000
Alternatively, changing your code to use IPv6 and using netcat without the -4
flag also works:
struct sockaddr_in6 my_addr;
...
if ( (*fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 )
return -1;
...
my_addr.sin6_family = AF_INET6;
my_addr.sin6_addr = in6addr_any;
my_addr.sin6_port = htons(port_no);
To show you how I debugged the problem: I first used netcat to start a UDP server, and send data to the server with a second netcat instance. This worked as expected. I then used strace
to inspect the system calls used by the netcat server. The strace
output shows netcat using IPv6:
...
socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(3, {sa_family=AF_INET6, sin6_port=htons(60000), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_scope_id=0}, 28) = 0
...
Besides that, there are two miscellaneous problems:
The
recv
function returns the number of bytes received or-1
in case of an error. For this reason, the type of the return value isssize_t
, instead ofsize_t
. Since your code declaressize_t recvlen
, whenrecv
returns-1
an integer underflow will occur andrecv
will be the maximum possible value of typesize_t
(e.g.ULLONG_MAX = 18446744073709551615
on my platform). This would then result in a buffer overrun, asbuf
is much smaller.Your
echo
/xxd
call produces only zeros for me. I'm not sure if this intended. The-r
flag forxxd
enables "reverse" mode, wherexxd
will attempt to parse a hexdump (e.g. as produced byxxd
without the-r
flag) and then reproduces the raw byte sequence that was the input to the original hexdump. But in your case, theecho
outputs raw binary data, not an encoded hexdump, hence this data cannot be parsed byxxd
in reverse mode.
How to send a file using netcat and then keep the connection alive?
Perhaps you were doing:
cat MY_FILE - | ncat ...
(Note that I've intentionally mispelled netcat, because I believe ncat
is a superior program.)
How can I send a byte (or bytes) to test a socket listening in my application?
You should not be using telnet for this.
Better option is to use netcat.
Then, pipe your command through bash
EG.
echo -n 0x03 | nc 127.0.0.1 1234
Turn simple C program into server using netcat
There's a high chance stdout
is not line-buffered when writing to a non-terminal. Do an fflush(stdout)
just after the printf
.
Receive binary data from a TCP server and save it to a file
Here is an example of connecting to a remote server, receiving data, and writing it to a file:
-module(recv).
-export([example/1]).
recv_data(IoDevice, Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, B} ->
ok = file:write(IoDevice, B),
recv_data(IoDevice, Sock);
{error, Reason} ->
error_logger:info_msg("Done receiving data: ~p~n", [Reason]),
file:close(IoDevice),
gen_tcp:close(Sock)
end.
example(FileName) ->
{ok, IoDevice} = file:open(FileName, [write, binary]),
{ok, Sock} = gen_tcp:connect("www.google.com", 80, [binary, {packet, raw}, {active, false}]),
ok = gen_tcp:send(Sock, "GET / HTTP/1.0\r\n\r\n"),
recv_data(IoDevice, Sock).
This will connect to google and write the response to a file:
Erlang R14A (erts-5.8) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.8 (abort with ^G)
1> c(recv).
{ok,recv}
2> recv:example("/tmp/test.bin").
=INFO REPORT==== 4-Nov-2010::08:52:59 ===
Done receiving data: closed
ok
3>
Free tool to send binary data to IP address and port?
I found a freeware tool named TCP/IP Builder.
But if you found a better free tool, please let me know.
Related Topics
Installing Gcc on Linux Without C Compiler
Why Do We Need to Call Poll_Wait in Poll
Sorting CSV File by 5Th Column Using Bash
Check If Opencv Is Compiled with Tbb
Jna Link Issue While Starting Cassandra Rhel 6.5
How to Timeout a Group of Commands in Bash
Flags in Objdump Output of Object File
Filename Last Modification Date Shell in Script
Makefile for Linux Kernel Module
Bash Not Trapping Interrupts During Rsync/Subshell Exec Statements
How to Set Runpath of a Binary
How to Monitor Newly Created File in a Directory with Bash
Case in Bash: "Line 4: Syntax Error Near Unexpected Token ')'"
How to Disable Specific Warning When -Wall Is Enabled