18

I'm trying to send a message through netcat. After sending the message, netcat must terminate.

I've tried the following:

cat tsmmessage.bin | nc -u localhost 4300
nc -u localhost 4300 < message.bin

The -q option states:

-q seconds

after EOF on stdin, wait the specified number of seconds and then quit. If seconds is negative, wait forever.

But

nc -q0 -u localhost 4300 < message.bin

also doesn't work.

What am I missing?

Frank Kusters
  • 323
  • 1
  • 2
  • 9
  • You should probably have used the `-q 0` flag with the pipe solution (with `cat`) instead of with the redirection solution (`<` ) – Camion Feb 07 '22 at 14:30

5 Answers5

15

Assuming that after sending EOF connection will stay idle, you can use -w timeout option, which works for timeout being equal to zero (unlike stupid -q option...)

cat tsmmessage.bin | nc -u localhost 4300 -w0
Bora M. Alper
  • 310
  • 2
  • 10
  • 1
    This is the correct answer and must be the accepted one rather than `-q`. – ccpizza Nov 13 '17 at 18:07
  • 3
    zero time out doesn't work on my machine (debian stretch). it says `invalid wait-time 0` – Anubis Apr 20 '18 at 10:47
  • On debian stretch and debain buster, `-w0` doesn't work. I've used `-w 1` instead (with the space) and it works fine – ciencia Apr 01 '21 at 11:00
  • Looking at the manpage, -q seems to be the right solution to THIS problem, though : This problem seems quite one way and doesn't suggest that the server side is replying anything on the connection. Why do you disregard the -q 0 solution ? To me it looks that that `-w …` is only useful if you want the receiver side to stop at the end of data. – Camion Feb 07 '22 at 14:59
5

Without the -q flag your instance of netcat will wait forever. There's no "end of stream" message with UDP so there is no way for netcat to know that both stdin and the network connection have finished.

For example, using TCP/IP this works as expected:

nc -l localhost 4300                     # Window 1
nc localhost 4300 </etc/group            # Window 2

But as you have determined, using UDP/IP this never ends:

nc -u -l localhost 4300                  # Window 1
nc -u localhost 4300 </etc/group         # Window 2

This is where the -q flag comes in. But unfortunately it doesn't accept a value of 0. It also won't accept non-integer values. Here is the best alternative I can offer without recourse to timeout or some other external utility:

nc -u -l localhost 4300                  # Window 1
nc -q 1 -u localhost 4300 </etc/group    # Window 2

Even here, it's not possible to have the listening netcat time out gracefully. (The -w timeout option is ignored, and -q is irrelevant.) Something like this might be of use in a practical situation, so that the netcat is killed after 90 seconds:

timeout 90 nc -u -l localhost 4300       # Window 1
nc -q 1 -u localhost 4300 </etc/group    # Window 2
roaima
  • 107,089
  • 14
  • 139
  • 261
  • `-q 0` works for me. – AlikElzin-kilaka Nov 11 '18 at 08:52
  • @AlikElzin-kilaka doesn't work for me though. You're definitely using UDP in your tests? What version of netcat do you have? You're probably on a more recent version. – roaima Nov 11 '18 at 09:01
  • Your first example on TCP/IP does not seem to work on Arch Linux, GNU Netcat, 0.7.1. It hangs. Also, the syntax for `nc -l` changed since then. – Michaël Oct 21 '20 at 03:45
  • @roaima, UDP only influence the fact that the receiver side knows that the sender side has stopped. However the receiver side is not part of this problem. To stop the receiver, you need `-w` – Camion Feb 07 '22 at 15:02
  • @Camion yes, except that `-w` is (or was, back in 2017) ignored in this context – roaima Feb 07 '22 at 16:09
  • @roaima Was it ignored on the _receiver_ side ? – Camion Feb 07 '22 at 16:14
  • 1
    I would have to assume so, because I wrote, "_Even here, it's not possible to have the listening netcat time out gracefully. (The -w timeout option is ignored, and -q is irrelevant.)_" – roaima Feb 07 '22 at 16:16
  • Oh, sorry, I replied to your comment, without paying attention to the fact that you were th one who wrote the answer – Camion Feb 07 '22 at 16:54
  • No worries, @Camion, there are (at least) two different versions of `netcat` using slightly different syntax. It may well be that the version I used to create this answer has improved its functionality, or it may be that the "other" version is the dominant one these days – roaima Feb 07 '22 at 16:57
3

udp

# listen on receiver
nc -u -l localhost -p 4300

# sender
cat tsmmessage.bin | nc -u -N -q 0 localhost 4300

tcp

# listen on receiver
nc -l localhost -p 4300

# sender
cat tsmmessage.bin | nc -N localhost 4300

Edit: This solutions worked for openbsd-netcat for according to the comments, and does not work for GNU Netcat in Archlinux

krazedkrish
  • 139
  • 4
-1

Stumbled upon this when Googling regarding pretty much the same problem. It turned out the issue was that netcat got killed by bash right after all the data got sucked in, without getting any chance to receive the response.

My solution to this was to add some delay after piping the data, like this:

(echo INFO; sleep 1) | nc redis.service.consul 6379

With a file this can look like:

(cat tsmmessage.bin; sleep 5) | nc -u localhost 4300
Rui F Ribeiro
  • 55,929
  • 26
  • 146
  • 227
SkyWriter
  • 99
  • 2
  • `netcat` still doesn't close when `sleep` finishes. I would expect the first command line to return to the prompt after 1 second, but it doesn't. – Frank Kusters Jun 01 '16 at 09:35
  • how about adding `-q 1`? i.e. `(echo INFO; sleep 1) | nc -q 1 redis.service.consul 6379`? – SkyWriter Jun 01 '16 at 09:36
  • With `-q` everything works, even the example in my original question. I've moved to a newer version of Ubuntu since then, maybe that causes the difference. – Frank Kusters Jun 01 '16 at 10:00
  • That's weird. Anyways, glad we both found a way around this :) – SkyWriter Jun 01 '16 at 17:32
-1

A fairly portable option is to send SIGHUP to the client instance of nc. Examples:

kill -1 <pid of nc>

OR

pkill -1 nc

This also works if the data stream was already finished and you need to close the connection cleanly but nc is left running. This can happen in an environment where the closing did not work due to portability issues.