netcat — nc — talks raw TCP and UDP: no protocol, no handshake beyond the connection, just bytes across a socket. That minimalism makes it the pocket knife of networking: port checks, ad-hoc servers, file transfers, protocol experiments.
The daily job: is that port open? #
$ nc -zv aospix.com 443
Connection to aospix.com 443 port [tcp/https] succeeded!
$ nc -zv db.internal 5432 && echo "postgres reachable"
-z scans without sending data, -v narrates. Unlike ping, this tests the service port, not ICMP — the honest check when a firewall drops ping but the app should answer. In scripts it is the wait-for-it idiom:
$ until nc -z localhost 8080; do sleep 1; done
$ echo "service is up"
Two netcats, one conversation #
On two machines (or two terminals), netcat becomes a chat channel — anything typed on one side arrives on the other:
$ nc -l 9990 # A: listen
$ nc host-a.example 9990 # B: connect
The same shape moves a file, tar stream included, with zero setup:
$ nc -l 9990 > backup.tar.gz # receiver first
$ tar czf - project/ | nc receiver.example 9990 # sender pipes in
The other tricks #
| Task | Command | |
|---|---|---|
| One-shot HTTP by hand | `printf 'GET / HTTP/1.0\r\n\r\n' \ | nc host 80` |
| Ad-hoc UDP check | nc -u -zv host 53 | |
| Serve a file once | nc -l 9990 < notes.txt | |
| Keep serving (loop) | while true; do nc -l 9990 < page.html; done | |
| Banner grab | nc host 22 and read the version string |
Speaking a protocol by hand — typing an HTTP request or SMTP greeting into a raw socket — is how protocols stop being magic; curl is the polished version, nc the laboratory.
ncat, nc.openbsd, and friends #
The name nc maps to several implementations (OpenBSD nc, ncat from Nmap, traditional netcat); flags differ subtly — -N (shutdown on EOF) exists in some, --exec in others. nc -h on the machine you are on is the ground truth, and worth checking before relying on exotic flags in scripts that must run elsewhere.
For structured checks above raw sockets, see ss and curl. The network series continues.
