Mark Needham

Thoughts on Software Development

netcat: Strange behaviour with UDP – only receives first packet sent

with 4 comments

I was playing around with netcat yesterday to create a client and server which would communicate via UDP packets and I rediscovered some “weird” behaviour which I’d previously encountered but not explained.

I started up a netcat server listening for UDP packets on port 9000 of my machine:

$ nc -kluv localhost 9000

We can check with lsof what running that command has done:

$ lsof -Pni :9000
COMMAND   PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
nc      63289 markhneedham    5u  IPv6 0xc99222a54b3975b5      0t0  UDP [::1]:9000

We can see that the netcat process is listening on port 9000 so let’s send it a UDP packet, using another netcat process:

$ echo "mark" | nc -vvu localhost 9000 -4
Connection to localhost 9000 port [udp/cslistener] succeeded!

We can see the sending of the UDP packet was successful and it shows up on the netcat server’s terminal as well.

$ nc -kluv localhost 9000
XXXXmark

If we ‘Ctrl-C’ the netcat client and run it again we’ll notice that it’s still able to connect to the port but we don’t see the message in the netcat server’s terminal:

$ echo "mike" | nc -vvu localhost 9000 -4
Connection to localhost 9000 port [udp/cslistener] succeeded!
$ nc -kluv localhost 9000
XXXXmark

I wasn’t sure what was going on but eventually came across an explanation by David Schwartz:

When nc is listening to a UDP socket, it ‘locks on’ to the source port and source IP of the first packet it receives.

As soon as it received its first datagram (from port 52832), it issued a connect system call ‘connecting’ it to the 127.0.0.1:52832. For UDP, a connect rejects all packets that don’t match the IP and port in the connect.

If we use lsof again we can see that we have exactly the same problem:

$ lsof -Pni :9000
COMMAND   PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
nc      63508 markhneedham    5u  IPv6 0xc99222a54b394c5d      0t0  UDP [::1]:9000->[::1]:63732

In our case the netcat server has created a connection between port 9000 and port 63732 and rejects packets coming in from any other IP/port combination.

I thought ‘Ctrl-C’ on the netcat client would kill the connection but it doesn’t.

At this stage I wasn’t sure what to do but Nathan pointed out that if I made use of timeouts on the client and server then it would be possible to send multiple UDP packets.

I restarted the netcat server but this time with a 1 second timeout:

$ nc -kluvw 1 localhost 9000

And then started sending UDP packets from a netcat client also with a 1 second timeout:

$ echo -e "all" | nc -vvuw 1 localhost 9000
Connection to localhost 9000 port [udp/cslistener] succeeded!
$ echo -e "the" | nc -vvuw 1 localhost 9000
Connection to localhost 9000 port [udp/cslistener] succeeded!
$ echo -e "udp" | nc -vvuw 1 localhost 9000
Connection to localhost 9000 port [udp/cslistener] succeeded!
$ echo -e "packets" | nc -vvuw 1 localhost 9000
Connection to localhost 9000 port [udp/cslistener] succeeded!

And the netcat server now receives all of them:

$ nc -kluvw 1 localhost 9000
XXXXall
XXXXthe
XXXXudp
XXXXpackets

If we increase the client timeout a bit so that we can run lsof while it’s connected we can see that the connection exists for the duration of the timeout:

$ lsof -Pni :9000
COMMAND   PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
nc      64317 markhneedham    5u  IPv6 0xc99222a54b394c5d      0t0  UDP [::1]:9000
nc      64541 markhneedham    5u  IPv6 0xc99222a54cc0101d      0t0  UDP [::1]:55792->[::1]:9000

But then once it’s finished it goes back to generally listening for UDP packets on that port which is exactly what we want:

$ lsof -Pni :9000
COMMAND   PID         USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
nc      64317 markhneedham    5u  IPv6 0xc99222a54b394c5d      0t0  UDP [::1]:9000
Be Sociable, Share!

Written by Mark Needham

July 30th, 2013 at 6:01 am

Posted in Networking

Tagged with

  • j0ey2069

    Thanks a million! Having this same issue. Makes perfect sense!

  • Richard Falk

    Thanks! This was a great help for setting up a simple UDP server (listener) for testing receiving from clients.

  • Afanasii Kurakin

    Thanks, however man nc says ‘The -w flag has no effect on the -l option’

  • Prasanna Ramesh

    I am facing the same issue. Have tried the same command in server side

    nc -kluvw 1 localhost 9000. Even though its not working out
    COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
    nc 7860 prasanna 3u IPv4 206184 0t0 UDP 127.0.0.1:9000->127.0.0.1:36790