168

I want to send only one short value in a UDP packet, but running the command

echo -n "hello" | nc -4u localhost 8000 

I can see that the server is getting the hello stuff but I have to press Ctrl+c to quit the netcat command.

How can I make it quit after sending hello?


Sorry, for the noise, I re-read the man page and found the -q option.

 echo -n "hello" | nc -4u -q1 localhost 8000 

works (it quits after 1 second).

For some reason it does not work with -q0.

1
  • Man page on debian: -q seconds: after EOF on stdin, wait the specified number of seconds and then quit. If seconds is negative, wait forever. Commented Jul 16, 2016 at 20:20

7 Answers 7

267

If you are using bash, you might as well write

echo -n "hello" >/dev/udp/localhost/8000 

and avoid all the idiosyncrasies and incompatibilities of netcat.

This also works sending to other hosts, ex:

echo -n "hello" >/dev/udp/remotehost/8000 

These are not "real" devices on the file system, but bash "special" aliases. There is additional information in the Bash Manual.

Sign up to request clarification or add additional context in comments.

17 Comments

Ok, you are right, let me just make it explicit that this won't work with ZSH.
This is way better than mucking with netcat. Thanks for the tip!
For some reason, I needed to use 127.0.0.1 instead on localhost on Ubuntu 14.04. (Yes, I do have localhost in /etc/hosts.)
/dev/udp/ is not a real file. It's only a file name interpreted specially by bash.
@JohnyTex Yes, because it only exists in bash, not in ls.
|
56

I did not find the -q1 option on my netcat. Instead I used the -w1 option. Below is the bash script I did to send an udp packet to any host and port:

#!/bin/bash def_host=localhost def_port=43211 HOST=${2:-$def_host} PORT=${3:-$def_port} echo -n "$1" | nc -4u -w1 $HOST $PORT 

1 Comment

OS X works this: "echo -n "test" | nc -4u -w0 localhost 9999" as SimonW says
17

On a current netcat (v0.7.1) you have a -c switch:

-c, --close close connection on EOF from stdin 

Hence,

echo "hi" | nc -cu localhost 8000 

should do the trick.

2 Comments

Important to note that this is true only for GNU netcat, but not for BSD netcat.
For clarity, with Linux-based netcat, the -c option requires a command as an argument, which "executes the given argument via /bin/bash" - commandlinux.com/man-page/man1/nc.1.html
13

I had the same problem but I use -w 0 option to send only one packet and quit. You should use this command :

echo -n "hello" | nc -4u -w0 localhost 8000 

3 Comments

nc 1.10-41+b1 does not accept -w0. Error: invalid wait-time 0
@palik that looks like a nc.traditional version string. -q0 should work for you.
echo '/api/add|0.002' | nc -4u -w1 127.0.0.1 5170 works for me : Ubuntu 20.04 bash
9

Unfortunately nc is not a unique name for a single tool. To find out which nc you have, look at the first line of output from nc -h. To send a single UDP packet and exit immediately, use the appropriate arguments for your specific nc.

  • GNU nc -uc localhost 8000 <<<hello
  • BSD nc -uq0 localhost 8000 <<<hello
  • traditional nc -uq0 localhost 8000 <<<hello
  • BusyBox nc does not support UDP
  • Others? Please leave a comment!

Related but thankfully not calling themselves nc:

  • nmap: ncat -u --send-only localhost 8000 <<<hello
  • bash: echo hello >/dev/udp/localhost/8000
  • socat - UDP:localhost:8000 <<<hello
  • sendip -p ipv4 -p udp -ud 8000 -d $'hello\n' localhost
  • packetsender -ua localhost 8000 $'hello\n'
  • There are so many more! But the original question was about netcat...

If you want a portable nc wrapper for sending a single UDP packet, try this as nc-udp-oneshot.sh:

#!/bin/sh helpword=$(nc -h 2>&1 | awk '{print$1;exit}') case $helpword in *GNU*) args=-uc ;; *) args=-uq0 ;; esac exec nc $args "$@" 

Now you can run echo -n hello | ./nc-udp-oneshot.sh with whichever nc happens to be installed. Or xxd -r -p <<<68656c6c6f | ./nc-udp-oneshot.sh for sending more complicated binary data, represented in hex.

Comments

7

Netcat sends one packet per newline. So you're fine. If you do anything more complex then you might need something else.

I was fooling around with Wireshark when I realized this. Don't know if it helps.

4 Comments

I think this is only correct for TCP. With UDP, it will send multiple lines in one packet (if they fit).
No. Simply test echo -n "hello\nworld" >/dev/udp/localhost/514 and you'll get 2 lines
@bebbo, 2 lines, one packet
@bebbo is right. This answer wasn't even correct for UDP specifically as it does this in TCP
0

Use -w0

echo -n "hello" | nc -4u -w0 localhost 8000

From @simon-unsworth 's answer below.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.