Lição 07 · Unit 2 · Networking for a Backend Engineer & Application Support
Unit 2, In Practice: Read a Live Connection
You told me Unit 2 landed only roughly — you got the big idea (FIN vs RST
vs silence) but the terminal felt awkward and the practical part didn't stick.
That wasn't you: two of those exercises were simply broken — one asked you to
watch a connection that closes faster than you can look, the other waited for a
timeout that an unroutable address can never produce. This lesson fixes both and
adds no new concepts — it re-walks the three Unit 2 moves, hands on the keys,
against a real service, in a way that actually works. Do it, don't read it.
Move 1 — what's listening, what's connected (on something real)
Pick a service you actually run — your app on its dev port, Postgres on 5432, anything. Then ask the box the two questions that open every connection debug:
| Question | Linux | macOS |
|---|---|---|
| What's listening? | ss -tlnp | lsof -nP -iTCP -sTCP:LISTEN |
| What's connected? | ss -tnp | lsof -nP -iTCP -sTCP:ESTABLISHED |
| fallback (either OS) | netstat -tlnp | netstat -an -p tcp |
Find your service in the LISTEN output. Now catch a live connection — and
here's the trap that bit you in Unit 2: a normal request finishes in under a
millisecond, so curl … & then ss shows nothing, because the connection
already closed. So hold one open by hand (bash opens a raw TCP socket on a file
descriptor and sits on it):
exec 3<>/dev/tcp/127.0.0.1/<PORT> # open a connection and HOLD it
ss -tnp | grep <PORT> # now the live connection is there to see
exec 3>&- # release it when you're done lookingYou'll see <PORT> on two lines — same port, two directions — the 4-tuple
in action:
- LISTEN
- A process parked on a port, waiting. Answers "who accepts connections here?"
- ESTAB / ESTABLISHED
- A live connection. Answers "who is connected right now?"
- The 4-tuple
(local IP, local port, peer IP, peer port). Your service keeps one listening port; each client shows up with a different ephemeral port, so every live connection is a distinct tuple. That's how one port serves thousands at once.
Do this against your own running service now. Seeing your process on your port is what turns "sockets" from a word into a thing you can point at.
Move 2 — the one fork that decodes every failure
This is the bit you rated most important, and the one inline question you missed in Unit 2 — so we drill it properly. When a connection doesn't open, the far side did exactly one of three things:
- Refused (
RST) - The host answered — with a reset. It's up, the packet arrived, nothing was listening. Because it answered, this rules out the network path and the firewall.
curlexit7. - No route / unreachable
- The network answered — a router said "can't get there." Also a rung-below-the-app problem, but note it answered, so it's closer to refused than to timeout. Often exit
7, and it fails fast. - Timeout (silence)
- Nothing came back at all. The packet vanished — a firewall dropping silently, dead host, or bad route. Silence rules out nothing except "actively refused."
curlexit28, and it waits.
Practice — produce each signature on purpose (this is where Unit 2 broke)
refused — the easy one. Point curl at a local port with nothing on it
(confirm it's free with ss -tlnp first):
curl -v http://127.0.0.1:9999/
# → curl: (7) Failed to connect ... Connection refused (an RST came back)unreachable — this is what you actually saw with the "black hole", and it was correct. An address with no route answers fast, because your own kernel says "I can't get there":
curl -v --connect-timeout 3 http://192.0.2.1/
# → curl: (7) ... Network is unreachable / No route to host (in a few ms)timeout — the one you can't fake with a bad address, because a timeout is silence, and silence means a packet was dropped — your own kernel won't silently drop its outbound packets, it errors fast. To see a real timeout locally you install the drop yourself with a firewall rule (fully reversible):
python3 -m http.server 8080 & # a real listener
sudo iptables -I OUTPUT -p tcp --dport 8080 -j DROP # eat the SYNs silently
curl -v --connect-timeout 3 http://127.0.0.1:8080/ # now it HANGS, then (28)
sudo iptables -D OUTPUT -p tcp --dport 8080 -j DROP # undo it
kill %1curl: (7) ... Connection refused. Which suspect does that let you cross off?
A connect attempt hangs, then fails with exit (28). What did the far side do?
curl fails instantly with No route to host. This is closer to…
Your reflex for any failed connection — do it in this order:
When this feels automatic on your own machines, you're ready for rung 1 done properly: DNS. Next lesson.
everything curl — Exit codes
(Daniel Stenberg) for 7/28/56, and the course
Failure Alphabet for
the one-page mechanism/rules-out map to keep beside you.
Sou seu professor — traga suas perguntas difíceis de “mas por quê”. Exporte seu progresso na página do curso e cole no /teach.