TCP Three-Way Handshake
Prompt
Walk me through what happens on the wire when a TCP connection opens — SYN, SYN-ACK, ACK — and then convince me why it has to be three messages and not two.
How this round runs
This is a conversation that escalates — I'll keep asking "and what happens when…" until I find the edge of what you know. I'm looking for the why behind the third message and how the connection behaves under packet loss, not a memorized recitation of the three steps.
Model answer
I'll go client → server and pin down what each message establishes, because the "why three"
falls out of that. The client sends SYN carrying its initial sequence number — call it
x. The server replies SYN-ACK: it acknowledges x+1 and sends its own initial
sequence number y. The client sends ACK of y+1. After that both sides know, and know
that the other knows, the starting sequence numbers in both directions.
That last clause is the whole argument for three messages. TCP is reliable and full-duplex,
so each direction needs its own synchronized sequence number, and each side needs
confirmation the other received its number. Two messages can synchronize and confirm one
direction, but the server would have sent y without any proof the client got it — the
server can't safely send data yet. The third message is the client confirming the server's
sequence number; only then is the reverse direction proven. So it's not ceremony, it's the
minimum to mutually agree on two independent sequence spaces over a lossy channel. The
sequence numbers being randomized also matters for security — a predictable ISN lets an
off-path attacker forge a segment or inject into the stream.
Under loss it degrades exactly where you'd expect, which is the interesting edge. If the
final ACK is lost, the server sits in SYN_RECEIVED, retransmits its SYN-ACK on a timer
(exponential backoff), and gives up after a bound — meanwhile the client may already think
it's ESTABLISHED and send data, whose ACK then completes the handshake anyway. A flood
of SYNs with no final ACK is the SYN-flood DoS, which SYN cookies defend by not
allocating state until the ACK returns. And on close, TIME_WAIT on the side that closed
actively holds the socket for ~2×MSL — my honest read on the exact value: it's two maximum
segment lifetimes, to absorb a delayed duplicate FIN/segment and stop it from corrupting a
new connection reusing the same port pair; the precise MSL is OS-tunable and I'd check the
platform rather than quote a hard number.
- Framed it as synchronizing two independent sequence spaces, not just 'three steps'
- Derived 'why three' from mutual confirmation: each direction needs proof the other received its ISN
- Reached for the security angle unprompted: randomized ISNs prevent off-path forgery
- Predicted loss behavior: lost final ACK → SYN_RECEIVED + retransmit; the SYN-flood DoS and SYN cookies
- Honest on TIME_WAIT: explained 2×MSL's purpose but flagged the exact MSL as OS-tunable
- Why does the side that closes sit in TIME_WAIT instead of freeing the socket immediately? → to absorb delayed duplicate segments / the final ACK and protect a reused port pair
- And what happens when the third ACK is lost but the client starts sending data? → the data's ACK completes the handshake; the server leaves SYN_RECEIVED
- A flood of SYNs with no final ACK — what breaks and what defends it? → half-open table exhaustion (SYN flood); SYN cookies avoid allocating state until the ACK