Send a Binary File (Line by Line) to a Socket Server with Netcat

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 is ssize_t, instead of size_t. Since your code declares size_t recvlen, when recv returns -1 an integer underflow will occur and recv will be the maximum possible value of type size_t (e.g. ULLONG_MAX = 18446744073709551615 on my platform). This would then result in a buffer overrun, as buf is much smaller.

  • Your echo/xxd call produces only zeros for me. I'm not sure if this intended. The -r flag for xxd enables "reverse" mode, where xxd will attempt to parse a hexdump (e.g. as produced by xxd without the -r flag) and then reproduces the raw byte sequence that was the input to the original hexdump. But in your case, the echo outputs raw binary data, not an encoded hexdump, hence this data cannot be parsed by xxd 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



Leave a reply



Submit