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?
answer
- count what occupies sequence space
- SYN and FIN each take one
- a pure ACK takes none
- ACK equals last byte plus one
basics
~20 sThe 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 sTwo 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
Remember that the acknowledgment number is the next byte expected, and that SYN and FIN each use up one sequence number.
Produce the full trace without hesitation, including the repeated sequence number on the pure ACK and the data segment, and explain SEG.LEN.
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.
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.