The TCP Three-Way Handshake
Three messages to agree a connection exists, four to agree it does not — and why it cannot be two.
Skip to the animationThe three-way handshake is how two machines agree that a connection exists and on what sequence number each direction will start from — and it takes three messages because two can never make both sides certain.
What has to be agreed
TCP offers a reliable, ordered byte stream over a network that guarantees none of it. To do that, both ends must hold matching state: buffers, window sizes, and above all a starting sequence number for each direction. The handshake is how that state gets established.
- 1Client → SYN with its own random initial sequence number
x. - 2Server → SYN + ACK: acknowledges
x+1and sends its own randomy. - 3Client → ACK of
y+1. Both ends are now ESTABLISHED.
Why three messages
This is the exam question, and the answer is about certainty rather than about data. After message 2 the client knows both sequence numbers — but the server has no evidence that its SYN arrived at all. Message 3 is what tells it.
Both directions need to be confirmed, so both need an acknowledgement — four events in principle. The server's ACK and its SYN can ride in one segment, so it collapses to three. It cannot collapse to two, because the last message sent is never itself acknowledged, and somebody has to be sure.
Initial sequence numbers are random for security: predictable numbers let an off-path attacker forge segments into a connection they cannot observe. They also stop a delayed segment from a previous connection on the same port pair being accepted as current.
The states
| State | Side | Means |
|---|---|---|
| LISTEN | server | waiting for a SYN |
| SYN-SENT | client | sent a SYN, waiting for SYN+ACK |
| SYN-RECEIVED | server | sent SYN+ACK, waiting for the final ACK |
| ESTABLISHED | both | data may flow in both directions |
| FIN-WAIT-1 / 2 | closer | sent FIN, waiting for ACK, then for their FIN |
| CLOSE-WAIT | other side | peer has finished; this side may still send |
| LAST-ACK | other side | sent its own FIN, waiting for the final ACK |
| TIME-WAIT | closer | waiting 2×MSL before really closing |
Why closing takes four
A FIN closes one direction only. When the client finishes, the server may still have data to send, so it acknowledges the FIN at once but keeps the other direction open — CLOSE-WAIT. Its own FIN comes later, when it is genuinely done. That gap is what stops the ACK and the FIN being combined the way they were during setup.
TIME-WAIT then holds the closing side for twice the maximum segment lifetime. If the final ACK is lost, the peer resends its FIN and somebody must still be there to answer it; and any straggling segment must expire before the same port pair could be reused. A busy server with thousands of sockets in TIME-WAIT is working correctly, not leaking.
What it costs
One full round trip before a single byte of application data can move — and with TLS on top, historically two more. For a page fetching resources from many hosts that is most of the perceived latency, which is why TLS 1.3 cut its handshake to one round trip and QUIC merged the transport and crypto handshakes into zero for a repeat visit.
Advantages and disadvantages
Advantages
- Both ends finish certain the other is there and agreed on sequence numbers.
- Random initial sequence numbers resist off-path forgery and stale-segment confusion.
- The four-way close never discards data still in flight in the other direction.
Disadvantages
- A full round trip of latency before any data moves.
- Half-open connections consume server state, which SYN floods exploit directly.
- TIME-WAIT ties up port pairs long after the conversation is over.
Watch it work
Check yourself
question 1 / 4
One question at a time. Pick an answer to see why it is right or wrong, then move on — there is no score to keep and nothing is saved.