TCP Three-Way Handshake
01Why three packets, not two?
A two-way handshake (SYN + SYN-ACK) lets the server confirm it received the client's SYN, but the client has no way to confirm the server's SYN-ACK arrived. TCP is full-duplex — data flows both ways — so both sides need to synchronize sequence numbers in both directions. The third packet (ACK) closes this loop: it proves the client received the server's sequence number and the connection is genuinely bidirectional.
02The three steps in detail
Step 1 — SYN: the client picks a random Initial Sequence Number (ISN) X and sends a SYN packet. Step 2 — SYN-ACK: the server picks its own ISN Y, acknowledges the client's ISN with ACK=X+1, and sends SYN=Y. Step 3 — ACK: the client acknowledges the server's ISN with ACK=Y+1. After this, both sides know each other's starting sequence numbers and the connection is ESTABLISHED.
Client Server
|---SYN (seq=X)--------->|
|<--SYN-ACK (seq=Y,------|
| ack=X+1) |
|---ACK (ack=Y+1)------->|
| [DATA FLOWS NOW] |03Sequence numbers and why they are random
If sequence numbers started at 0, an attacker who observed a past connection could predict the sequence numbers of a new connection between the same hosts and inject forged packets. Randomizing the ISN makes this practically impossible. It also prevents stale packets from a previous connection (which might still be in transit) from being accepted by a new connection between the same endpoints.
04Connection teardown: the 4-way FIN
Unlike the handshake, teardown takes four packets because either side can close its sending direction independently (half-close). The side that wants to close sends FIN; the other side ACKs immediately, then may continue sending data before sending its own FIN. The originator ACKs that FIN and enters TIME_WAIT — waiting 2×MSL (Maximum Segment Lifetime) before fully closing, to ensure any delayed packets are gone.