4.3.19 · D2Computer Networks

Visual walkthrough — TCP — header, connection (3-way handshake, 4-way termination)

3,016 words14 min readBack to topic

We assume you know zero about TCP. We will earn every symbol before we use it.


Step 1 — What is a "byte stream", really?

WHAT. Imagine you want to send the message HELLO from one computer (call it Client) to another (call it Server). To a computer, letters are just numbers, and the whole message is a line of little boxes, one box per byte.

WHY start here. Everything TCP does is counting these boxes. If we don't picture the boxes first, "sequence number 1001" is meaningless. So we lay the boxes on a number line.

PICTURE. Look at the row of boxes below. Each box is one byte. Underneath each box is its position — its index on the stream. TCP's whole job is to make sure the boxes arrive in this exact order with none missing.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 2 — Why we can't start counting at zero

WHAT. You might think: "just number the first byte , then , then ..." Simple. But TCP does not start at . It starts at a random number chosen at connection time, called the Initial Sequence Number (ISN).

WHY a random start. Suppose two computers open a connection, close it, then open another one using the same ports. Old, delayed packets from the first connection might still be floating in the network. If both connections started counting at , a stale old packet could look like a valid new one and corrupt the stream. Starting each connection at a fresh random ISN makes those stale packets land on impossible positions, so they get thrown away.

PICTURE. The same box-row as before, but now the position labels start at the ISN instead of . The first byte sits at position , the next at , and so on.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 3 — The two number lines (full-duplex)

WHAT. A TCP connection carries data in both directions at the same time: Client → Server and Server → Client. These are two separate streams, each with its own boxes and its own ISN.

WHY two lines. Client's boxes and Server's boxes are unrelated messages. Client might be uploading a file while Server sends back status text. You cannot describe two independent streams with one counter — so each direction gets its own number line.

PICTURE. Two number lines stacked. The top line (orange) starts at Client's ISN . The bottom line (teal) starts at Server's ISN . Notice they start at different numbers and grow independently.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 4 — What "acknowledgment = next expected" means

WHAT. When a side receives boxes, it reports back how far it has read using the Acknowledgment number (ACK). The rule: ACK is the position of the next box I am waiting for, i.e. one past the last box I successfully got.

WHY "next expected" and not "last received". Saying "next expected" makes it cumulative: a single ACK number silently confirms every box before . If box is missing, the receiver keeps asking for no matter how many later boxes arrive — a clean, unambiguous signal of exactly where the gap is.

PICTURE. Server has received boxes at positions (green, done). The red arrow points at position — the first box not yet received. That is the ACK number Server sends back.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 5 — The "+1" mystery: SYN eats a phantom box

WHAT. The handshake's first segment carries no real data — it just says "let's start, my ISN is ." This segment has the SYN flag set (SYN = "synchronise"). Yet the reply acks , not . Where did that phantom box come from?

WHY SYN takes a slot. TCP wants the SYN itself to be reliable — if it's lost, it must be retransmitted and re-detected like any byte. The trick: pretend the SYN occupies one imaginary box on the number line at position . It carries no data, but it consumes the position. So the first real data byte lands at , and acking "I got your SYN" means "next I want ."

PICTURE. The Client's number line with a dashed phantom box at position labelled SYN. The real data boxes begin at . The Server's ACK arrow points at .

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 6 — Putting it together: the 3-way handshake as arrows on two lines

WHAT. Now we can read the entire handshake as movements on the two number lines from Step 3. Let Client ISN , Server ISN .

WHY three messages. Both sides must (a) announce their ISN and (b) hear the other confirm it. That's naively four events, but the middle two — Server confirming Client's SYN and Server sending its own SYN — ride in one segment (SYN+ACK). So four collapse into three.

PICTURE. A time diagram: Client on the left, Server on the right, time flowing downward. Each arrow is labelled with its flags, seq, and ack. Watch the phantom-box "+1" appear in every ack.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 7 — Edge case: simultaneous open (both send SYN at once)

WHAT. Usually one side (Client) sends its SYN first and the other (Server) replies with SYN+ACK. But two peers can each decide to connect at the same instant and both fire a bare SYN before either has seen the other's. This is a simultaneous open.

WHY it still works in "three". Each SYN crosses the other in flight. When a peer receives the other side's SYN, it doesn't need to send a fresh SYN — it already sent one — so it just sends an ACK for what it received. There is no single SYN+ACK segment; instead each side emits SYN, then ACK, and the two ACKs cross too. Counting distinct segment types per side it is still symmetric SYN-then-ACK; both lines end up synchronised.

PICTURE. Both timelines fire a SYN outward at the same height; the arrows cross in the middle. Then each side answers with an ACK of the SYN it received.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 8 — Edge case: the teardown is not symmetric

WHAT. Closing is different from opening. First, name the counters: by the time either side closes, its sequence counter has advanced past all its sent data. Let = the position of Client's FIN box (one past Client's last sent data byte), and = the position of Server's FIN box (one past Server's last sent data byte). At setup, one SYN+ACK merged two jobs. At teardown, each side closes its own direction with a FIN, and the two closings need not happen together — this is called a half-close.

WHY four messages. After Client says "I'm done sending" (FIN at box ), Server might still have data to send. So Server can only ack the FIN right away; its own FIN (at box ) comes later, once it too is finished. That splits into four arrows: FIN, ACK, FIN, ACK.

PICTURE. Time diagram of teardown. Between Server's ACK (message 2) and Server's FIN (message 3), a shaded band shows Server still sending data — the half-close gap that stops the ACK and FIN from merging.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

Step 9 — Degenerate case: the number line is finite (32-bit wrap-around)

WHAT. We have drawn the number line as if it goes on forever. It does not. A sequence number is a 32-bit value, so it lives in the range to . When you count past the top, it wraps back to 0 — like an odometer rolling over. All arithmetic is done modulo .

WHY this matters. On a fast link you can send bytes ( GB) and the counter loops. After wrap, a later byte can have a smaller raw number than an earlier one (e.g. earlier , later ). A naive "bigger number = later byte" test would order them backwards. So TCP never compares raw magnitudes; it compares differences modulo : byte is "before" byte if the wrapped gap is less than half the space ().

PICTURE. The number line bent into a circle of positions. A marker passes the top and reappears at 0. Two points near the wrap show how "distance the short way round" gives the correct order.

Figure — TCP — header, connection (3-way handshake, 4-way termination)

The one-picture summary

WHAT. One figure that compresses the whole life of a connection: the two number lines, the three setup arrows with their "+1"s, data flowing, then the four teardown arrows and TIME_WAIT.

Recall Feynman retelling — the whole walkthrough in plain words

Two friends want to pass notes reliably. First, each writes their notes as a line of numbered boxes (Step 1). But they don't start at box zero — each rolls a die for a secret starting number so old stray notes from a previous game can't sneak in (Step 2). Because notes fly both ways, there are two number lines, one per friend, starting at different numbers (Step 3). When a friend reports progress, they name the next box they're still waiting for, which quietly confirms every box before it (Step 4). The very first "hello" note (SYN) isn't real content, but it still uses up one box, which is why the reply says "next I want box " — the famous +1 (Step 5). Stack the two lines and the hello-dance is just three arrows (Step 6) — and even if both friends say hello at the same instant, the hellos just cross and each answers with an okay (Step 7, simultaneous open). Saying goodbye is trickier: each friend says "I'm done" separately at their own box or , because one might still have a last thing to say — so goodbye takes four arrows, not three (Step 8). One subtlety: each friend's box-counter is a wheel of slots, so after it rolls over you must measure "who's ahead" the short way round the wheel, not by raw size (Step 9). And whoever says goodbye first hangs around a little while in case their last "okay" got lost.

Recall Rebuild the "+1" from scratch

Why does acking a SYN or FIN add one? ::: The SYN/FIN carries no data but occupies one phantom box on the number line, so the next expected byte is one position later. Why do setup and teardown differ in message count? ::: Setup merges Server's ACK and SYN into one segment; teardown can't merge Server's ACK and FIN because Server may still be sending (half-close). Why can't we order bytes by raw number size? ::: Sequence numbers are 32-bit and wrap modulo 2^32, so after a wrap a smaller raw number can be the later byte; compare gaps the short way round the circle.


Connections

  • Parent topic
  • Reliable Data Transfer Principles (the number-line + cumulative-ACK idea in general)
  • Sliding Window & Flow Control (many boxes in flight; the Window field)
  • Sockets & Ports (which two processes own these two number lines)
  • UDP — connectionless transport (contrast: no ISN, no handshake, no boxes to count)
  • TCP Congestion Control (how fast we send boxes once the lines are set up)
  • IP — packet structure & routing (the envelope each segment rides inside)