11

Is there a way to know when netcat is done transferring a file between machines?

Current commands:

Machine #2: nc -lp 5555 > test.txt

Machine #1: nc MachineIP Port < test.txt

The transfer happens, but there's no visual indication that it has completed.

19

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.

  • I can't seem to get this to work. When I do -q it says the command doesn't exist. I see -w look similar but this doesn't cause the connection to quit – Anthony Russell Aug 25 '16 at 16:19
  • What's your nc version? To check: nc -h, first line. – user147505 Aug 25 '16 at 16:28
  • ehh yeah it's pretty old. Im on an old image of linux. I will update it and give it another go – Anthony Russell Aug 25 '16 at 16:34
  • I updated my answer. – user147505 Aug 25 '16 at 20:31
  • 1
    When all packets don't come across, operating system will detect this and retransmit them without application noticing (or if that still fails, 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. – Juraj Aug 25 '16 at 21:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.