Moving Files
Because a socket is just stdin in one direction and stdout in the other, a file transfer is two redirections facing each other. The lab's payload is the shipped specimen, copied 200 times so there's enough of it to matter:
$ wc -c payload.txt; sha256sum payload.txt
49200 payload.txt
4269a2a243bb386ef678ed333ab20b3db7c16f3ae16a776f2b5072879f23baf2 payload.txt
Push: sender connects to a waiting receiver
$ nc -l 127.0.0.1 45001 > received.txt & # receiving side, started first
$ nc -N 127.0.0.1 45001 < payload.txt; echo "sender exit: $?"
sender exit: 0
$ wc -c received.txt; sha256sum received.txt
49200 received.txt
4269a2a243bb386ef678ed333ab20b3db7c16f3ae16a776f2b5072879f23baf2 received.txt
$ cmp payload.txt received.txt && echo IDENTICAL
IDENTICAL
The order of operations is the whole
technique: the receiver starts
first and waits; the sender connects,
streams the file, and -N gives the
receiver the end-of-file signal that
makes its netcat exit and close
received.txt. Then the proof, which
is not optional: same byte count, same
SHA-256, and cmp silent — byte for
byte identical.
Pull: the file waits, the receiver comes to it
$ nc -l 127.0.0.1 45001 < payload.txt & # serving side: whoever connects gets the file, once
$ nc -N -w 3 127.0.0.1 45001 > pulled.txt; echo "receiver exit: $?"
receiver exit: 0
$ sha256sum payload.txt pulled.txt
4269a2a243bb386ef678ed333ab20b3db7c16f3ae16a776f2b5072879f23baf2 payload.txt
4269a2a243bb386ef678ed333ab20b3db7c16f3ae16a776f2b5072879f23baf2 pulled.txt
$ cmp payload.txt pulled.txt && echo IDENTICAL
IDENTICAL
Same file, opposite initiative. This direction reads naturally ("the file is on that machine; go get it") and has the sharpest edge in the chapter, stated plainly in the comment: the serving netcat hands the file to whoever connects first, once, and exits. No password, no names, no "are you sure." On loopback that's a lab. On a network it's a giveaway — see chapter 11 before you serve anything this way anywhere else.
When nobody is listening
$ nc -N -w 3 127.0.0.1 45001 > nothing.txt; echo "exit: $?" # nobody is listening this time
exit: 1
$ wc -c nothing.txt
0 nothing.txt
Silent (no -v), exit 1, and an empty
file created by your own redirection —
not by netcat. The receiver-side moral:
an empty output file means the
transfer never started, and the
sender-side moral is chapter 5's:
without -v, failure says nothing; the
exit code is the witness.
What this is not
Netcat file transfer is a party trick with real uses (next chapter and chapter 11), and its limits are part of the trick:
- No resume. A connection that dies
at 90% delivers a 90% file and
starts over from nothing.
rsyncexists because of this sentence. - No encryption, no integrity built in. The bytes are plaintext on the wire, and the only proof of arrival is the hash you run. (On loopback, plaintext is a fact; on a network, it's a decision — chapter 11.)
- No directories, no metadata. One
stream of bytes: no filename, no
permissions, no timestamps cross the
wire. The name
received.txtwas chosen by the receiving command, not sent by the sender. - The sender doesn't know you got it all. Exit 0 means the bytes left. The hash comparison is the only "it arrived" in the system.
Check: after either transfer,
sha256sum on both ends must print the
same string, and cmp must say nothing
at all. If the hashes differ, believe
them, not the exit codes — the usual
cause is a transfer cut short (chapter
8's missing -N, or a receiver started
late), and the fix is to redo it, not
to trust the partial file.