Skip to content
shellmap

Test a TCP connection with nc

Confirm whether you can open a TCP socket to host:port — the basic "is this thing reachable" check before debugging deeper protocol issues.

How to test a tcp connection with nc in each shell

Bashunix
nc -zv -w 3 example.com 443

`-z` = zero-IO (just probe), `-v` = verbose (prints success/fail), `-w 3` = 3-second timeout. Bash-builtin alternative needing no nc: `timeout 3 bash -c "</dev/tcp/example.com/443" && echo open || echo closed`.

Zshunix
nc -zv -w 3 example.com 443
Fishunix
nc -zv -w 3 example.com 443
PowerShellwindows
Test-NetConnection -ComputerName example.com -Port 443 -InformationLevel Quiet

`-InformationLevel Quiet` returns just `$true`/`$false`. Without it, prints multi-line table. Win8+/Server 2012+ (NetTCPIP module). SLOW on closed ports (~21s — runs DNS + ICMP + TCP all sequentially).

cmd.exewindows
powershell -NoProfile -Command "Test-NetConnection -ComputerName example.com -Port 443 -InformationLevel Quiet"

cmd has no native TCP probe. `telnet example.com 443` once worked but Telnet Client is not installed by default since Win10 (enable via `Enable-WindowsOptionalFeature -Online -FeatureName TelnetClient`).

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **`nc` is THREE different binaries**: (1) **OpenBSD nc** — base on macOS and OpenBSD, also packaged as `openbsd-netcat` on Debian/Ubuntu. Supports `-z`, `-w SECONDS` timeout, `-N` to close stdin on EOF, `-U` for Unix domain sockets. (2) **GNU nc (netcat-traditional)** — older Debian/Ubuntu default. Supports `-z`, `-w` but NOT `-N` (`-q 0` is the equivalent). (3) **`ncat`** — Nmap project, more features (TLS, SOCKS proxy, brokering), shipped as `nmap-ncat` on RHEL/Fedora. `nc --version` distinguishes them. The `-z`/`-w` flags work across all three for the "just probe" case — divergence appears with stdin/stdout handling.
  • **Bash builtin `/dev/tcp/HOST/PORT` is a hidden gem** for ad-hoc TCP testing without `nc` installed: `timeout 3 bash -c "</dev/tcp/example.com/443" 2>/dev/null && echo open || echo closed`. Pseudo-file — bash translates the path into a `socket(AF_INET, SOCK_STREAM, 0)` + `connect()`. **Only works in bash + ksh** (NOT in dash, fish, sh, busybox sh). Useful in slim Docker images that have bash but lack nc. The same idiom with output: `(echo > /dev/tcp/example.com/443) && echo open` — but no timeout knob unless wrapped with `timeout`.
  • **pwsh `Test-NetConnection` is SLOW on closed ports** — it runs DNS → ICMP ping → TCP connect serially with no short-circuit, so a closed port often takes 21s (default ping timeout). Faster: `(New-Object System.Net.Sockets.TcpClient).ConnectAsync("example.com", 443).Wait(3000)` — returns immediately on success, returns false at 3000ms on timeout, throws on connection refused. Wrapper: `function Test-Tcp($h, $p, $ms=3000) { $c = New-Object Net.Sockets.TcpClient; try { $c.ConnectAsync($h, $p).Wait($ms) } finally { $c.Close() } }`. For batch testing across many ports/hosts, the async pattern is 50× faster than `Test-NetConnection` in a `ForEach-Object`.
  • **Connection state interpretation**: a successful `nc -z` proves the kernel returned `SYN-ACK` (TCP handshake completed) — it does NOT prove the application behind the port is healthy. `nc -zv :22` succeeds the instant `sshd` is listening, even mid-startup when it would refuse auth. For HTTP, a proper health check is `curl -fsS http://host:port/health` (`-f` returns non-zero on 4xx/5xx, `-S` shows errors on failure, `-s` suppresses progress). For TLS, `openssl s_client -connect host:port -servername host < /dev/null` verifies the handshake + presents the cert chain (essential for SNI debugging).
  • **UDP testing is harder**: `nc -uzv host port` "succeeds" most of the time because UDP has no handshake — the kernel sends a packet and `nc` returns immediately. The only true negative is an ICMP "port unreachable" message back, which happens if and only if no socket is bound AND the firewall doesn't silently drop it (most firewalls do drop). For DNS specifically: `dig @8.8.8.8 +tries=1 +time=3 google.com` actually tests UDP/53 reachability by attempting a real query. For NTP: `ntpdate -q server` queries without setting the clock. There's no general-purpose UDP probe — protocol-specific tests are the right approach.

Related commands

Related tasks