4.3.19 · D3Computer Networks

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

2,759 words13 min readBack to topic

Before any symbols, three names you must know cold:

  • ISN = Initial Sequence Number = the byte-position each side chooses to start counting from when a connection opens. It is not always 0 (it is picked semi-randomly for safety), which is exactly why the handshake has to announce it.
  • seq (sequence number) = the byte-stream index of the first data byte in this segment. Think of a long ribbon of bytes; seq is "where on the ribbon this piece starts."
  • ack (acknowledgment number) = "the next byte I expect from you." Not the last one I got — the next one I want.

And two phantom rules that trip everyone:

  • SYN consumes 1 sequence number.
  • FIN consumes 1 sequence number.

A note on the maths writing: expressions inside dollar signs like are just formatted maths — read as "2 to the power 32". The symbol means "the remainder after dividing", and is literally the percent sign. Everything below is just the two counters plus the two phantom rules applied carefully.


The scenario matrix

The table lists every case class this topic can produce. Each worked example afterwards is tagged with the cell it covers.

# Case class What makes it tricky Example
A Normal setup, non-zero data plain seq arithmetic Ex 1
B Zero-length data segment (pure ACK) seq does not advance Ex 2
C SYN / FIN phantom byte seq advances by 1 with no real data Ex 1, Ex 5
D Multi-segment stream chaining seq across segments Ex 3
E Degenerate: lost segment + retransmit ACK stays put (cumulative) Ex 4
F Limiting: sequence-number wrap-around at modular arithmetic Ex 6
G Asymmetric teardown / half-close server sends data after client's FIN Ex 5
H Real-world word problem (throughput vs header) overhead accounting Ex 7
I Exam twist: who is in TIME_WAIT & duration role-based, not machine-based Ex 8

Modular arithmetic reminder (used only in Ex 6): the sequence field is 32 bits wide, so it counts and then wraps back to 0 — like a car odometer rolling over. We write .


Worked Examples

Example 1 — Normal setup with data (cells A, C)

Forecast: guess the client's data segment seq before reading. Is it 1000 or 1001?

  1. C→S: SYN, seq = 1000. Why this step? The client offers its ISN; SYN just proposes "let's start counting here."
  2. S→C: SYN, ACK, seq = 5000, ack = 1001. Why this step? Server acks the SYN. SYN consumed slot 1000, so the next expected byte is . Server piggybacks its own ISN 5000.
  3. C→S: ACK, seq = 1001, ack = 5001. Why this step? Client's SYN used slot 1000, so its next seq is 1001. It acks the server's phantom SYN byte: .
  4. C→S: data, seq = 1001, ack = 5001, len = 200. Why this step? The pure ACK in step 3 carried no data, so seq did not advance. The first real byte therefore sits at 1001.

Verify: After 200 bytes, the client's next seq should be . The server, on receiving these 200 bytes, will send ack . Consistent.


Example 2 — Pure ACK carries zero data (cell B)

Forecast: does the pure ACK "use up" seq 1201?

  1. Receive 200 bytes; the server's data started at seq 5001. Why this step? We derived 5001 in Example 1 — it is the server's first data byte (server ISN 5000, +1 for its phantom SYN). To acknowledge, we compute next expected .
  2. Send pure ACK, ack = 5201, seq = 1201, len = 0. Why this step? The client's own send-seq is still 1201 (unchanged since Example 1). A segment carrying no data and no SYN/FIN consumes zero sequence numbers, so seq stays 1201.
  3. Send data segment, seq = 1201. Why this step? Because the pure ACK consumed nothing, seq is unchanged from before it.

Verify: Sequence numbers only advance by (payload length) + (1 if SYN) + (1 if FIN). For the pure ACK that is , so the client's seq stays 1201; and the ack it sends is . ✓


Example 3 — Chaining across multiple segments (cell D)

Forecast: what's the seq of the third segment?

  1. Segment 1: seq = 1001, len = 500. Why this step? Starts at the first data byte.
  2. Segment 2: seq = 1001 + 500 = 1501, len = 500. Why this step? Next seq = previous seq + previous payload length.
  3. Segment 3: seq = 1501 + 500 = 2001, len = 300. Why this step? Same rule again — chaining is just repeated addition.
  4. Server final ACK: ack = 2001 + 300 = 2301. Why this step? ACK = next byte expected = one past the last byte received.

Verify: Total bytes . Last byte index . Next expected . ✓


Example 4 — Lost segment, cumulative ACK (cell E, degenerate)

The figure below draws the byte ribbon: two green blocks (A and C) arrived, the middle coral block (B) is lost, and the lavender arrow shows the server's ACK pinned to 1501 — it cannot move past the hole. Follow the arrow as you read the steps.

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

Forecast: after C arrives, does the ACK jump to 2301?

  1. A arrives (1001..1500). Server acks 1501. Why this step? Cumulative ACK = next contiguous byte expected; A ends at 1500, so next is 1501 (green block A in the figure).
  2. C arrives (2001..2300) but B (1501..2000) is still missing. Why this step? TCP's basic ACK is cumulative — it can only report the highest contiguous byte. There is a hole at 1501 (the faded coral block B in the figure).
  3. Server re-sends ack = 1501 (a duplicate ACK). Why this step? It cannot ack 2301 — bytes 1501..2000 never arrived. It still wants 1501, exactly where the lavender arrow points.

Verify: Cumulative ack is always (highest contiguous byte received) + 1. Highest contiguous is 1500 (from A), so ack = 1501 — unchanged by C's arrival. This duplicate ACK is exactly what triggers fast retransmit in TCP Congestion Control / Sliding Window & Flow Control. ✓


Example 5 — Half-close teardown with trailing data (cells G, C)

The ladder diagram below shows time flowing downward, client on the left and server on the right. Read the four arrows top-to-bottom: the client's FIN, the server's ACK, the server's trailing 100 bytes of data, the server's own FIN, and the client's final ACK — after which the client sits in TIME_WAIT. Notice the server keeps sending after the client has closed: that asymmetry is why teardown needs four messages.

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

Forecast: what is the seq of the server's FIN — 9000 or 9100?

  1. Segment 1 — C→S: FIN, seq = 8000, ack = 9000. Why this step? Client is done sending; FIN marks the end of the client→server stream. Its ack = 9000 means "the next server byte I expect is 9000" (the server has not sent those 100 bytes yet).
  2. Segment 2 — S→C: ACK, seq = 9000, ack = 8001. Why this step? FIN consumes one sequence number, so the next byte expected from the client is . The server is not ready to close — this is the half-close. Its own seq is still 9000 because it has sent no data yet.
  3. Segment 3 — S→C: data(100) then FIN, seq of FIN = 9100, ack = 8001. Why this step? The server flushes its remaining 100 bytes (occupying 9000..9099) and then sends FIN at . Its ack stays 8001 (nothing new from the client). This is the single "teardown message" from the server that finally closes its direction.
  4. Segment 4 — C→S: ACK, seq = 8001, ack = 9101. Then client enters TIME_WAIT. Why this step? The server's FIN consumed one seq (at 9100), so the next byte expected is . The client's own seq is 8001 (its FIN used slot 8000).

Verify: Server sends 100 data bytes then 1 FIN byte starting at 9000, so the FIN sits at seq ; the client's final ack = . The client's FIN used slot 8000, so the server's ack-of-FIN = . ✓


Example 6 — Sequence-number wrap-around (cell F, limiting)

Forecast: does the number just keep growing to 4294967400, or does something else happen?

  1. Naive sum: . Why this step? Sequence numbers advance by payload length — the rule doesn't change at the edge.
  2. Reduce modulo : . Why this step? The field is only 32 bits; it cannot hold . Like an odometer rolling from 999...9 back to 0, the counter wraps: we take the remainder after dividing by (that is what means).
  3. Next seq = . Why this step? Exactly the remainder computed above.

Verify: The 200 bytes occupy indices (that's 96 bytes to reach the top) and then (the remaining 104 bytes). . Next free slot = 104. ✓


Example 7 — Real-world overhead word problem (cell H)

Forecast: guess — is it above or below 25%?

  1. Total bytes per packet = data + TCP header + IP header. Why this step? Every byte on the wire counts, not just payload.
  2. Efficiency = data / total. Why this step? "Fraction that is application data" is exactly payload over everything.
  3. As a percentage: . Why this step? Multiply by 100 to convert a fraction to a percentage ( is just the percent sign).

Verify: Overhead = header bytes out of , i.e. overhead; data share . ✓ This is why tiny segments are wasteful — it motivates Nagle's algorithm and larger MSS.


Example 8 — Exam twist: TIME_WAIT owner & duration (cell I)

Forecast: "server feels in charge" — but does that matter here?

  1. Identify the active closer = whoever sends the first FIN. Why this step? TIME_WAIT is a role, not a machine. Here the server sent the first FIN, so the server is the active closer.
  2. The active closer enters TIME_WAIT → the server does. Why this step? Only the side that sent the last ACK (the active closer) must linger to protect against a lost final ACK.
  3. Duration = seconds. Why this step? TIME_WAIT lasts so any straggling duplicate can die out and a re-sent peer FIN can be re-acked.

Verify: s. The "server can't be in TIME_WAIT" belief is the classic trap — it's role-based. ✓


Active Recall

Recall Cover the answers and test yourself

What does ISN stand for? ::: Initial Sequence Number — the byte position each side starts counting from Client ISN 1000, after handshake first data seq? ::: 1001 (SYN ate slot 1000) Does a pure ACK advance seq? ::: No — 0 payload, 0 SYN/FIN → 0 consumed Segment starts at 1001 with 1300 bytes total sent; final ack? ::: 2301 Server got A(1001,500) and C(2001,300) but B lost; ack? ::: 1501 (cumulative, hole at 1501) Seq 4294967200 + 200 bytes, 32-bit field, next seq? ::: 104 (wrap mod 2^32) 10 B data + 20 B TCP + 20 B IP: data fraction? ::: 20 percent Server sends first FIN, MSL 2 min: who waits, how long? ::: Server (active closer), 240 s


Connections

  • Parent · Hinglish version
  • Sliding Window & Flow Control (cumulative ACK & duplicate ACKs, Ex 4)
  • TCP Congestion Control (duplicate ACKs trigger fast retransmit)
  • Reliable Data Transfer Principles (sequence numbering, retransmission)
  • IP — packet structure & routing (the 20-byte IP header in Ex 7)
  • UDP — connectionless transport (no handshake, no seq — contrast)
  • Sockets & Ports (which process owns the connection)