The Three-Way Handshake
SYN → SYN-ACK → ACK: how every connection begins
Step 1 of 2 — understand the idea. Read this first and the packet trace will confirm what you already expect, instead of teaching you two things at once.
What you'll be able to do
- ▸Explain why TCP needs a handshake before any data flows
- ▸Identify the SYN, SYN-ACK, and ACK packets and their key fields
- ▸Trace how both Initial Sequence Numbers are exchanged and confirmed
- ▸Name the state each host is in after every packet
- "Alpha, do you read me?"
- → SYN — the client announces its own starting number
- "I read you, Alpha — this is Bravo"
- → SYN-ACK — one packet doing both jobs
- "I read you, Bravo"
- → ACK — the client confirms the server's number
- the name each gives
- → the Initial Sequence Number each side chooses at random
Where it breaks down: Radio operators can hear whether the channel is noisy; TCP cannot. It has no idea whether the path is good until it starts losing segments. And a radio check confirms the link, whereas a completed handshake says nothing about whether the application behind the socket is healthy — a server can accept the connection and then never read a byte.
✗ Common misunderstanding: A successful three-way handshake means the application is up and ready.
Why that's wrong: The handshake is completed by the operating system's TCP stack. A listening socket can be accepted by the kernel while the application behind it is hung, still starting, or broken.
Correct model: The handshake proves a socket is listening and the path works in both directions — nothing about application health.
The packets prove it: The handshake trace reaches ESTABLISHED with zero application bytes exchanged; the server's process is never consulted.
✗ Common misunderstanding: The SYN packet carries the first application data.
Why that's wrong: In classic TCP the SYN carries options and the ISN, but no payload — data flows only after the handshake completes. (TCP Fast Open is a separate, later extension.)
Correct model: Handshake first, data second. The SYN's job is synchronising sequence numbers and announcing capabilities.
The packets prove it: Select the SYN in any trace: Len=0, and the payload field is absent entirely.
Watch these fields in the lab: tcp.flags.syn · tcp.sequenceNumber
- 1The server has already called listen() and sits in the LISTEN state, doing nothing but waiting. No packets are involved yet.
- 2The client's OS picks an unused ephemeral port (here 49512) so this connection's 5-tuple will be unique.
- 3Each side independently chooses a random Initial Sequence Number — the starting point for numbering its own outgoing bytes.
- 4The client sends SYN, announcing its ISN and its capabilities (MSS, window scale, SACK-permitted, timestamps).
- 5The server replies SYN-ACK: acknowledging the client's ISN + 1, announcing its own ISN, and stating its own capabilities.
- 6The client sends ACK, acknowledging the server's ISN + 1. Both sequence spaces are now confirmed and the connection is ESTABLISHED — with zero application data sent so far.
Watch these fields in the lab: tcp.flags.syn · tcp.flags.ack · tcp.sequenceNumber · tcp.ackNumber
✓ Concept check — before you open the packets
These test the idea, not the trace. You should be able to answer them from the explanation above.
Now that you understand the concept, observe how it appears in the packet exchange.
The lab runs a real simulated capture — pause, step, click any packet, and inspect every byte.