Skip to content
The Three-Way Handshake
step 1/5

Reading — step 1 of 5

Read

~3 min readUDP & TCP Basics

The Three-Way Handshake

TCP is reliable, ordered, and full-duplex — but before a single byte of data moves, both ends have to agree on where counting starts. Each direction of a connection carries its own sequence number stream, and neither side may assume the other starts at zero. The handshake exists to synchronize those two starting points. That is literally what the SYN flag means: synchronize.

Three segments do it:

Rendering diagram…
  1. Client picks its initial sequence number X and sends SYN, seq=X.
  2. Server picks its own Y, and in one segment both announces it (SYN, seq=Y) and acknowledges the client's (ack=X+1).
  3. Client acknowledges the server's SYN (ack=Y+1). The connection is now ESTABLISHED at both ends.

Why three and not two?

Reliability requires each side to prove to the other that its sequence number was received. The client learns its SYN arrived when the server ACKs it (segment 2). The server learns its SYN arrived when the client ACKs it (segment 3). Drop to two segments and the server never gets confirmation that the client heard its ISN — it would be sending into a void it cannot trust.

SYN costs a sequence number

Here is the detail behind most handshake bugs: the SYN flag consumes one sequence number, exactly as if it were one byte of data. That is why the acknowledgment is seq + 1, not seq. If the client's SYN is seq=X, the first data byte will be X+1, and the server's ack=X+1 says "I have everything through the SYN; send me byte X+1 next." The same rule holds for FIN at teardown. Miss it and every ACK you generate is off by one and the peer discards your segments.

Initial sequence numbers are random on purpose

X and Y are neither zero nor predictable. Randomizing the ISN does two jobs: it keeps a stray, delayed segment from an old connection on the same four-tuple from being mistaken for valid data, and it forces an off-path attacker to guess a 32-bit number to inject a forged segment. Modern stacks derive the ISN from a keyed hash (RFC 6528) rather than a bare clock.

What the SYN carries besides the ISN

The handshake is also where per-connection features are negotiated, as TCP options on the SYN and SYN-ACK:

  • MSS — the largest segment payload each side will accept (~1460 on Ethernet). Each side advertises its own; the smaller value governs.
  • Window scale — multiply the 16-bit window by 2^N so windows can exceed 64 KB.
  • SACK permitted — allow selective acknowledgment on this connection.
  • Timestamps — sharper RTT measurement and protection against wrapped sequence numbers.

An option offered only in the SYN is in force for the whole connection, or not at all — there is no renegotiation later.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…