核心 · Key Idea
In one line: the three-way handshake lets each side confirm "I can send / you can receive / you can send / I can receive"; the four-way termination exists because TCP is full duplex — each direction is closed independently.
What it is#
Handshake:
C → S SYN seq=x
C ← S SYN+ACK seq=y, ack=x+1
C → S ACK ack=y+1
Connection established.
Termination:
C → S FIN
C ← S ACK (got it; let me finish flushing)
C ← S FIN (I'm done too)
C → S ACK
Connection closed.
Analogy#
打个比方 · Analogy
Handshake = a phone call: "Hello?" "Hi!" "OK, let's talk." Each side checks "I can hear + you can hear" once. Termination = both sides agreeing to hang up: "I'm done speaking." "OK, let me finish too." (more bytes possible in between) "I'm done too." "OK, hanging up."
Key concepts#
SYNSynchronize
Step one — request to open, carries an initial sequence number.
ACKAcknowledge
Confirms receipt of a byte range. Every TCP segment carries an ACK field.
FINFinish
I'm done sending in this direction.
TIME_WAITTime Wait
Active closer waits 2*MSL (~60 s) before fully releasing — prevents stale segments from confusing a new connection on the same tuple.
Half-closeHalf-close
After one side FINs, the other can keep sending.
RSTReset
Forced abort, skips the four-way dance — common on closed ports / abnormal exits.
State machine#
In production, the two most common pains are TIME_WAIT accumulation (high-concurrency short-lived connections) and CLOSE_WAIT lingering (the app never called close()).
Practical notes#
netstat -an | awk '{print $6}' | sort | uniq -c— connection count per state.- Too many
TIME_WAITs? Enabletcp_tw_reuseon Linux to recycle. Avoidtcp_tw_recycle(removed since 4.12 — broke connectivity behind NAT). CLOSE_WAITis a bug. Your app received the peer's FIN but never called close(). Uselsofto find the leak.- SYN flood: forged SYNs fill the half-open queue. Enable
syncookiesas a defense. - TFO (TCP Fast Open): payload travels with the handshake, saving 1 RTT — but middleboxes / peers spotty support, not widely deployed.
Easy confusions#
Graceful FIN close
Four-way teardown, **pending data delivered**.
Application called close().
Application called close().
RST abort
Single RST packet, **unsent data may be lost**.
Port not listening / app crashed / SO_LINGER 0.
Port not listening / app crashed / SO_LINGER 0.