First some background
There are different versions of nc
, as you can find on nc(1) - Linux man page or nc(1) BSD General Commands Manual the connection should shut down right after the transfer. There's an example given on both linked sites:
Start by using nc to listen on a specific port, with output captured
into a file:
$ nc -l 1234 > filename.out
Using a second machine, connect to the listening nc process, feeding
it the file which is to be transferred:
$ nc host.example.com 1234 < filename.in
After the file has been transferred, the connection will close
automatically.
Your netcat
doesn't shut the connection after the transfer, so it is different from the one(s) described above. It behaves like mine, Netcat 1.10 on Debian Jessie. This behaviour is documented in /usr/share/doc/netcat-traditional/README.gz
(on my machine), the boldening is mine:
In the simplest usage, "nc host port" creates a TCP connection to the
given port on the given target host. Your standard input is then sent
to the host, and anything that comes back across the connection is
sent to your standard output. This continues indefinitely, until the
network side of the connection shuts down. Note that this behavior is
different from most other applications which shut everything down and
exit after an end-of-file on the standard input.
Here's the reasoning behind this behaviour:
You may be asking "why not just use telnet to connect to arbitrary
ports?" Valid question, and here are some reasons. Telnet has the
"standard input EOF" problem, so one must introduce calculated delays
in driving scripts to allow network output to finish. This is the
main reason netcat stays running until the network side closes.
Wikipedia has a run-down of different implementations. I can't name differences though. Maybe someone else can?
Now, solutions
1
You can tell nc
to quit after the file has been read. This option is useful:
-q seconds after EOF on stdin, wait the specified number of seconds
and then quit. If seconds is negative, wait forever.
If you use this command on the sending end:
nc -q 0 MachineIP Port < test.txt
nc
will quit 0 seconds after reading EOF, that is just after the file has ended. It will then exit and so will the receiving end nc
.
If you wonder what happens if the packets don't get across, here's a comment by Juraj.
When all packets don't come across, system will detect this and
retransmit them without application noticing (or if not possible,
application will get timeout error). Reliable delivery is the purpose
of TCP protocol provided by OS kernel, which nc
uses. You can request
UDP protocol that does not do this, using nc -u
but this is not the
case.
2
There's an original example in the aforementioned README.gz
, which is based on the -w
timeout and doesn't require the -q
option to be present in your implementation.
Netcat can be used as a simple data transfer agent, and it doesn't
really matter which end is the listener and which end is the client --
input at one side arrives at the other side as output. It is helpful
to start the listener at the receiving side with no timeout specified,
and then give the sending side a small timeout. That way the listener
stays listening until you contact it, and after data stops flowing the
client will time out, shut down, and take the listener with it.
Unless the intervening network is fraught with problems, this should
be completely reliable, and you can always increase the timeout. A
typical example of something "rsh" is often used for: on one side,
nc -l -p 1234 | uncompress -c | tar xvfp -
and then on the other side
tar cfp - /some/dir | compress -c | nc -w 3 othermachine 1234
will transfer the contents of a directory from one machine to another,
without having to worry about .rhosts files, user accounts, or inetd
configurations at either end.