Before TCP can ship any actual data, the client and server shake hands with three messages: SYN, SYN-ACK, ACK. This sets up sequence numbers and confirms both sides are alive.
In simple language: it’s like calling someone — “Hello?” “Hello!” “Great, let’s talk.” Three turns and we’re ready.
The Three Messages
- SYN — Client says “I want to connect. My starting sequence number is X.”
- SYN-ACK — Server says “Got it. My starting sequence number is Y, and I acknowledge yours (ack = X+1).”
- ACK — Client says “Confirmed. ack = Y+1.” Done — connection is ESTABLISHED.
The Handshake Timeline
Why Three Messages, Not Two?
Both sides need to synchronize sequence numbers AND prove they can hear each other.
- Message 1: client → server. Server learns client is alive + client’s seq#.
- Message 2: server → client. Client learns server is alive + server’s seq#.
- Message 3: client → server. Server learns its message reached the client.
Without the third message, the server wouldn’t know if its SYN-ACK got through.
Sequence Numbers — Why Random?
The initial sequence number (ISN) is chosen pseudo-randomly. Why not start at 0?
- Security — predictable seq numbers let attackers spoof packets in a session.
- Avoid collisions — old packets from a previous connection on the same 5-tuple shouldn’t get confused with the new one.
RFC 6528 defines how modern OSes pick ISNs.
Connection States
Each side moves through a state machine. The key states for the handshake:
Client: CLOSED -> SYN_SENT -> ESTABLISHED
Server: CLOSED -> LISTEN -> SYN_RCVD -> ESTABLISHED
We can see them live with:
ss -tan # Linux
netstat -an | grep -E 'SYN|ESTAB' # macOS / cross-platform
Watching It With tcpdump
sudo tcpdump -i any -n 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' and host example.com
# 14:00:01 IP 192.168.1.5.51234 > 93.184.216.34.443: Flags [S], seq 100
# 14:00:01 IP 93.184.216.34.443 > 192.168.1.5.51234: Flags [S.], seq 500, ack 101
# 14:00:01 IP 192.168.1.5.51234 > 93.184.216.34.443: Flags [.], ack 501
[S] = SYN, [S.] = SYN+ACK, [.] = ACK.
SYN Flood Attack
Send tons of SYN packets but never reply with the final ACK. The server keeps half-open connections in SYN_RCVD state, exhausting memory. Mitigation: SYN cookies — the server stores no state until the ACK arrives.
Latency Cost
The handshake takes 1 RTT (round-trip time) before any application data flows. To India ↔ US, that’s ~150ms doing nothing useful. This is one reason QUIC and TLS 1.3 0-RTT exist — to fold the handshake into the first useful message.
TCP Fast Open (TFO)
A modern extension: a client can include data in the initial SYN if it has a valid cookie from a previous connection. Saves an RTT on repeat visits.
Common Gotcha
People say “the handshake exchanges data” — it doesn’t. The handshake just sets up the connection. The first byte of HTTP doesn’t go out until after the third ACK.
Interview Tip
If asked to draw the handshake on a whiteboard, draw two vertical lines (client/server) and three diagonal arrows. Label each with the flags (SYN, SYN-ACK, ACK) and a sample seq/ack. Done — most interviewers want to see exactly that sketch.