BSD nc (netcat) does not terminate on EOF
Solution 1:
I, too, was puzzled by netcat's behavior, so I dug into the code. Here's the whole story:
nc servers (nc -l
) and clients only exit after the mutual connection was closed. That is, if each of the parties sent a FIN packet to the other party.
A server always sends a FIN
packet after receiving a FIN
packet from the client. (Unless the server already sent a FIN
packet.)
A client sends a FIN packet either:
- after
EOF
on stdin, when run with argument-N
- after
EOF
on stdin, when the server already sent a FIN packet
With option -d
stdin is ignored and nc
behaves as if it encountered EOF
on stdin.
Option -N
always implies sending FIN
after encountering EOF
on stdin.
Ways to exit the nc processes after exchanging data:
-
Georg's answer
server$ echo hello | nc -l -N 2000 client$ nc -d localhost 2000
After sending
hello
, the server encountersEOF
on stdin an sendsFIN
because of-N
.The client receives the message and, due to
-d
, seesEOF
on stdin and sendsFIN
, because the server already sentFIN
.The connection is closed, both the client and the server exit.
-
Client initiates the close
server$ echo hello | nc -l 2000 client$ nc -dN localhost 2000
The server keeps the connection open after
EOF
on stdin.The client sees
EOF
on stdin and sendsFIN
, because of-N
.The server sends
FIN
after receiving the client'sFIN
.The connection is closed, both the client and the server exit.
Solution 2:
nc
establishes a bi-directional connection. I.e. it sends stdin
from host B to host A as well as the desired one from A to B.
Use -d
on host B to ignore stdin
. -N
on host A is still needed to close the TCP
connection on EOF.
In summary
Host A:
tar cf - stuff | dd | nc -N -l 12987
Host B:
nc -d a.example.com 12987 | dd | tar tf -