skip to content

A TCP client with ISN 1000 connects to a server with ISN 8000, sends 200 bytes, then a FIN: which sequence and acknowledgment numbers appear?

level: middleimportance: must knowfreq 46%

answer

  1. count what occupies sequence space
  2. SYN and FIN each take one
  3. a pure ACK takes none
  4. ACK equals last byte plus one

basics

~20 s

The client's SYN uses 1000, so the server acknowledges 1001; data occupies 1001-1200 and is acknowledged with 1201; the FIN uses 1201 and is acknowledged with 1202. The server's SYN uses 8000, so the client acknowledges 8001.

solid answer

~40 s

Two rules do all the work: the acknowledgment number is the next byte expected, and only data bytes, SYN and FIN occupy sequence space. So the client's SYN carries `seq=1000` and the SYN-ACK acknowledges `1001`; the server's SYN uses 8000, so every client segment afterwards carries `ack=8001`. The client's third handshake segment is a pure ACK with `seq=1001`, and because it consumes nothing, the data segment also starts at `seq=1001` and covers 1001-1200. The server acknowledges `1201`. The FIN then carries `seq=1201`, occupies that one number, and is acknowledged with `1202`. The server's own sequence number stays 8001 throughout because it sends no data and no FIN in this trace.

go deeper

for a junior

Remember that the acknowledgment number is the next byte expected, and that SYN and FIN each use up one sequence number.

for a middle

Produce the full trace without hesitation, including the repeated sequence number on the pure ACK and the data segment, and explain SEG.LEN.

for a senior

Use the arithmetic to read a real exchange: spot an acknowledgment that is off by one, a FIN that was never acknowledged, or segments rejected by the window test.

for a principal

Explain why putting SYN and FIN into sequence space is the design choice that lets control signals be retransmitted and acknowledged like data.

## The two rules Every TCP sequence-number exercise reduces to two rules from **RFC 9293**: 1. **What occupies sequence space.** Each data byte takes one number. The **SYN** flag takes one number placed before the first data byte of its segment, and the **FIN** flag takes one number placed after the last data byte of its segment. Nothing else does: a pure ACK, an RST, or a PSH flag on an empty segment consumes no sequence numbers. 2. **What an acknowledgment says.** The acknowledgment number is the **next sequence number the receiver expects**. It is cumulative, so it confirms everything below it. RFC 9293 folds rule 1 into one quantity: `SEG.LEN` counts the data octets **plus** SYN and FIN. The next sequence number after a segment is `SEG.SEQ + SEG.LEN`, and that is also the acknowledgment number that confirms it. ## The full trace Client ISN = 1000, server ISN = 8000. The client sends 200 bytes and then closes its sending direction. | # | Direction | Flags | seq | ack | SEG.LEN | Why | |---|---|---|---|---|---|---| | 1 | C to S | SYN | 1000 | (none) | 1 | SYN occupies 1000 | | 2 | S to C | SYN, ACK | 8000 | 1001 | 1 | acknowledges the client's SYN; own SYN occupies 8000 | | 3 | C to S | ACK | 1001 | 8001 | 0 | pure ACK consumes nothing | | 4 | C to S | ACK | 1001 | 8001 | 200 | data bytes 1001 to 1200 | | 5 | S to C | ACK | 8001 | 1201 | 0 | next byte expected is 1201 | | 6 | C to S | FIN, ACK | 1201 | 8001 | 1 | FIN occupies 1201 | | 7 | S to C | ACK | 8001 | 1202 | 0 | acknowledges the FIN | Points worth saying aloud in an interview: - Segments 3 and 4 carry the **same** sequence number, 1001. That surprises people, but it follows directly from a pure ACK having `SEG.LEN = 0`. A client may also put its data on segment 3 itself. - The last data byte is **1200**, not 1201: 200 bytes starting at 1001 end at 1001 + 200 - 1. - The server's `seq` stays at **8001** from segment 5 onward, because it sent no data and no FIN. - Sequence arithmetic wraps. Had the client's ISN been 4,294,967,200, the data would run from 4,294,967,201 through 2^32 - 1 and on to 104 after wrapping, and the server would acknowledge 105: RFC 9293 requires every addition and comparison to be done modulo 2^32. - The FIN must be acknowledged like data. Giving FIN a sequence number is exactly what lets TCP retransmit and acknowledge it without ambiguity: RFC 9293 says SYN and FIN are the only controls that need this protection. ## Checking a segment against the receive window The same arithmetic decides whether a receiver accepts a segment at all. RFC 9293 says a segment occupies valid receive space when its first or last byte falls inside the window: ```pseudocode # receiver state: RCV.NXT (next byte expected), RCV.WND (window size) last = SEG.SEQ + SEG.LEN - 1 acceptable = (RCV.NXT <= SEG.SEQ < RCV.NXT + RCV.WND) or (RCV.NXT <= last < RCV.NXT + RCV.WND) if not acceptable: if not RST: send <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> drop segment ``` All comparisons are **modulo 2^32**, because the 32-bit sequence space wraps. There are special cases for zero-length segments and a zero window: with a zero receive window, a segment carrying data is not acceptable at all. On the sending side, an incoming acknowledgment is new only when `SND.UNA < SEG.ACK =< SND.NXT`. An acknowledgment at or below `SND.UNA` is a duplicate; one above `SND.NXT` acknowledges something never sent, so the endpoint replies with an ACK and drops the segment. ## Mistakes that cost marks - Adding one for the handshake's final ACK, which makes data start at 1002. - Writing the acknowledgment number as the last byte received (1200) instead of the next expected (1201). - Forgetting that FIN consumes a number, which leaves the final ACK at 1201. - Counting segments instead of bytes, so that ACK numbers step by one per packet.

  • What does a TCP receiver do with a data segment whose bytes fall entirely outside its receive window?
    RFC 9293 treats it as unacceptable: unless the RST bit is set, the receiver sends an acknowledgment carrying its current `RCV.NXT` and drops the segment. The ACK re-tells the sender where the receiver really is, which repairs confusion after old duplicates or a stale retransmission. A segment only partly inside the window is trimmed to the part that fits, and data beyond `RCV.NXT` is held for later processing.
  • What happens if a TCP endpoint receives an acknowledgment for data it has not sent yet?
    An acknowledgment is acceptable only if `SND.UNA < SEG.ACK =< SND.NXT`. RFC 9293 says an ACK above `SND.NXT` acknowledges something not yet sent, so in the synchronized states the endpoint sends an ACK, drops the segment and changes no state. That check, together with the receive-window test, is what keeps stray or forged segments from moving a connection's counters.

saying these in an interview costs you the question

  • The handshake's final ACK consumes a sequence number, so data starts at 1002.
  • The acknowledgment number is the last byte received, so 200 bytes from 1001 are acknowledged with 1200.
  • A FIN carries no data, so it consumes no sequence number.
  • Sequence numbers step by one for each segment sent.
  • Each side starts its sequence numbers at zero on every connection.