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 -
Related videos on Youtube
georg
Updated on September 18, 2022Comments
-
georg almost 2 years
Host A:
tar cf - stuff | dd | nc -N -l 12987
Host B:
nc a.example.com 12987 | dd | tar tf -
On host A
dd
prints its summary aftertar
completes. Thus it is clear, that tar closes the pipe/file ->EOF
.165040+0 records in 165040+0 records out 84500480 bytes transferred in 25.464802 secs (3318325 bytes/sec)
On both hosts
nc
happily sits there without exiting.nc(1)
:-N shutdown(2) the network socket after EOF on the input. Some servers require this to finish their work.
Thus on host A
nc
should have seenEOF
, closed the damn socket and on host Bnc
should have seen the TCP connection terminate and should have closedstdout
(stdin
ofdd
/tar
).How do I tell
nc
to closestdout
/ terminate on host B and terminate on host A.nc
bug?-D
(debug) does nothing.nc
can't even tell its version number... sighBoth hosts are FreeBSD 10.3-RELEASE-p4, IPv4 only.
-
Jimm Chen over 4 yearsThank you. But you answer (2.) problematic. If server run
(echo hello; sleep 5; echo world;) | nc -l 2000
, client will only receivehello
and close TCP with FIN,world
will not be received. I have tried it on openSUSE 15.1.