TCP Worksheet — Study Guide

The three questions cover when a TCP receiver sends an ACK and how three duplicate ACKs make the sender retransmit; what goes wrong when a two-message handshake meets a request that was delayed in the network, and how TCP's three-message handshake avoids it; and why the server's starting number y has to be new and unpredictable.

Q1When does the receiver ACK?

1 · What an ACK number says

1–50 51–100 101–150 151–200 delivered missing held, out of order not yet sent Ack 51 — the first byte the receiver is still missing

The strip is a receiver's copy of the byte stream, numbered from byte 1 and cut into 50-byte segments (these are not the worksheet's numbers). A shaded box is a segment the receiver has; the dashed box is a segment that has not arrived.

A TCP ACK number is the number of the next byte the receiver expects §3.5.2, which is the first byte it is still missing, not the last byte it got. Here that is byte 51. The ACK is cumulative: one number says "everything before this has arrived", so the segments the receiver holds past the gap do not change it.

Host A is uploading a file to host B over a connection that is already established. Every segment A sends carries 100 bytes. The capture uses relative sequence numbers, so the first byte of the connection is byte 1. B sends no data of its own and has plenty of free buffer space.

A sends six segments back to back. The third of them, carrying bytes 201–300, is lost; every other segment arrives in the order it was sent. An ACK number names the next byte B expects. B decides what to send back using four rules:

RuleWhat arrives at BWhat B does
R1In-order segment, the byte B expected next. Nothing else is waiting to be ACKed. Wait up to 500 ms for another segment. If none comes, send the ACK.
R2In-order segment, the byte B expected next. One earlier segment is still waiting to be ACKed. Immediately send one cumulative ACK covering both.
R3Out-of-order segment: a higher sequence number than expected, so a gap has opened. Immediately re-send the ACK for the last in-order byte.
R4A segment that fills or partly fills the gap. Immediately send an ACK, provided the segment starts at the low end of the gap.
  1. 1

    For each segment that reaches B, give the rule that fires and the Ack number B puts in its reply. Write "none yet" where B does not send one. Row 1 is filled in as an example.

    #Arriving at BBytes it carriesRuleAck number B sends
    11st segment1–100R1none yet
    22nd segment101–200
    34th segment301–400
    45th segment401–500
    56th segment501–600
    63rd segment, resent by A201–300
  2. 2

    At the moment A decides to retransmit, which bytes does B actually have? Can A know that from the ACKs it has received?

Hint
After each arrival, which byte is B waiting for next? Does that number change when a segment arrives that is not that byte?
Bigger hint
Before choosing any rules, write B's next-expected byte beside every row: it is 101 after row 1. Then for each row ask whether the segment started at that byte (R1 or R2, depending on whether an ACK is already pending), started past it (R3), or filled the hole (R4). For part 2, list what B is holding beside each ACK it sends, and ask what the ACK number alone tells A about that list.
Answer

1R2 201 · R3 201 · R3 201 · R3 201 · R4 601

#Arriving at BBytes it carriesRuleAck number B sends
11st segment1–100R1none yet
22nd segment101–200R2201
34th segment301–400R3201
45th segment401–500R3201
56th segment501–600R3201
63rd segment, resent by A201–300R4601

Rows 1 and 2 belong together. When the first segment arrives nothing else is pending, so R1 holds its ACK back. The second segment arrives inside that wait with an ACK already pending, so R2 sends one cumulative ACK for both: Ack 201, the next byte B expects. This delayed ACK §3.5.4 is why a real capture shows about one ACK for every two segments.

Rows 3, 4 and 5 each bring a segment that starts past byte 201, so a gap is open and R3 fires every time: B immediately repeats the ACK for the last in-order byte, which is Ack 201 again. Row 6 is the resent segment, and it starts exactly at the low end of the gap, so R4 fires. It fills the only hole, B now holds every byte through 600, and one ACK, Ack 601, covers all of it.

If you wrote 200 in row 2, you gave the last byte B received rather than the next byte it expects. An ACK number is always the first byte the receiver is still missing (Figure 1). This is the same slip as on the Week 4 quiz.

2 · Q1 as a message-sequence diagram

Host A Host B 1–100 101–200 201–300 (lost) 301–400 401–500 501–600 R1 · hold the ACK R2 · Ack 201 R3 · Ack 201 duplicate 1 R3 · Ack 201 duplicate 2 R3 · Ack 201 duplicate 3 3rd duplicate arrives 201–300 resent R4 · Ack 601

The two vertical lines are hosts A and B, with time running downward. Each arrow is one segment: data from A on the left, labelled with the bytes it carries, and ACKs from B on the right, labelled with the rule that produced them. The ✕ is where the third segment is lost.

Count the arrows that carry Ack 201: there are four, and only the last three are duplicates.

Four ACKs carry Ack 201. The first, from row 2, is an ordinary cumulative ACK: it is new information, telling A that bytes 1–200 arrived. The three after it, from rows 3, 4 and 5, are duplicate ACKs, because they repeat a number A has already seen. TCP's fast retransmit §3.5.4 resends the oldest unACKed segment when three additional ACKs for the same data arrive. So A resends 201–300 when the third duplicate arrives, which is the fourth Ack 201 overall, and it does so without waiting for its timeout.

If you expected A to resend after three Ack 201s in total, you counted row 2's ACK as the first duplicate. It is not one: it was the first time A heard 201. The rule asks for three ACKs beyond that one, and an earlier trigger would resend segments that were only reordered, not lost.

2B has 1–200 and 301–600; A cannot tell

B has delivered bytes 1–200 and is holding 301–600 out of order. It is missing only 201–300. But every ACK A has received says the same thing, "the next byte I want is 201". From that A learns that something is missing and which byte it starts at, and nothing about what arrived after it. That is the cost of a cumulative ACK.

So A resends only the oldest unACKed segment and waits. The Ack 601 in row 6 is the first moment A learns that B already had 301–600. Had A also resent 301–600, it would have spent three segments on data the receiver was already holding.

If you said A knows B has 301–600 because it received three duplicates, you have read more into them than they carry. Three duplicates tell A that three later segments arrived, but not which ones; a duplicate ACK names only the gap.

The worksheet left two things out. It assumed A's window let it send six segments back to back, and it never let A's timeout fire. How large that window may be is flow control §3.5.5 and congestion control §3.7; how the timeout is set from measured round-trip times is §3.5.3.

§3.5 Connection-oriented Transport: TCP · video · video (part 2) · knowledge checks · practice problems

Figures after the authors' Chapter 3 slides, copyright © 1996–2025 J.F. Kurose and K.W. Ross.

Q2Two handshakes, one bad network

3 · The two servers' rules as state diagrams

2-WAY SERVER LISTEN ESTAB req_conn(x) arrives: allocate the connection and reply acc_conn(x) client closes no timer runs here 3-WAY SERVER (TCP) LISTEN SYN_RCVD ESTAB SYN(x): record x, pick a new y, reply SYN-ACK(y, ack = x+1) ACK(ack = y+1): allocate the connection timer expires: discard client closes

Each box is a state the server can be in, and each arrow is a move between states, labelled with the message or event that causes it and what the server does as it moves. The dashed arrow is the move made when a timer runs out. These are the same rules the question states in words below, drawn so the two servers can be compared.

The 2-way server has one arrow out of LISTEN, and it leads straight to ESTAB, where the connection is allocated. The 3-way server stops halfway, in SYN_RCVD §3.5.6, holding only x and its own new y, and it has a way back to LISTEN that does not need the client.

A connection cannot start until both sides agree they want it and agree on the sequence number each will start from. The network in this question may delay a message for a very long time without losing it, and either side retransmits anything it thinks went missing. Nothing is corrupted and nothing is lost forever. Here are both protocols.

2-way handshake

  • Client. Picks a starting number x and sends req_conn(x). Retransmits it if no reply comes back in time. Enters ESTAB when acc_conn(x) arrives.
  • Server. On receiving req_conn(x): records x, allocates the connection's buffers, enters ESTAB immediately, and replies acc_conn(x).
  • Server states: LISTEN → ESTAB. The server leaves ESTAB only when the connection is closed by a client, and it runs no timer while in ESTAB.

3-way handshake (TCP)

  • Client. Picks x and sends SYN(x). On receiving SYN-ACK(y, ack = x+1): enters ESTAB and replies ACK(ack = y+1).
  • Server. On receiving SYN(x): records x, picks a brand-new number y that it has never used before, replies SYN-ACK(y, ack = x+1), and enters SYN_RCVD. It does not allocate the connection yet. It enters ESTAB only when an ACK carrying ack = y+1 arrives.
  • Server states: LISTEN → SYN_RCVD → ESTAB. A SYN_RCVD entry has a timer running, and is thrown away if no matching ACK arrives. After a client closes the connection, the server returns to LISTEN.

Run this scenario for both protocols: The client's first request is delayed in the network. It retransmits, the connection is established, data is exchanged, and the client closes. Long afterwards, the delayed packet finally reaches the server.

2-WAY HANDSHAKE Client Server req_conn(x) delayed in the network req_conn(x) again L1 acc_conn(x) data flows client closes L2 …arrives at last L3 acc_conn(x) no one here 3-WAY HANDSHAKE Client Server SYN(x) delayed in the network SYN(x) again R1 SYN-ACK(y, ack = x+1) ACK(ack = y+1) R2 data flows client closes R3 …arrives at last R4 SYN-ACK(y′, ack = x+1) ? …never arrives

Each half has two vertical lines, the client on the left and the server on the right, with time running downward; each arrow is one message. The long dashed arrow is the client's first request, which leaves at the top and is not delivered until the bottom. The seven boxes, L1–L3 and R1–R4, are where the server's state is asked for. A ✕ on the client's line marks the client closing and, lower down, the point where there is no client any more. The dotted grey arrow at the bottom right is the message part 4 asks about.

  1. 1

    Write the server's state in each of the seven boxes, using only LISTEN, SYN_RCVD and ESTAB.

  2. 2

    Compare L1 and R1. The same message has just arrived at both servers. What resources has the 2-way server committed that the right-hand one has not?

  3. 3

    On the 2-way side, the server ends in the state you wrote in L3. Will it release any reserved resources?

  4. 4

    On the 3-way side, write on the dashed arrow the message that would have to arrive for the server to reach ESTAB. Give two reasons it never will — one about the client, and one about the number y′ itself.

Hint
At L1 and R1 the same message has just arrived. What is each server allowed to conclude from it, and what does each rule tell it to do next?
Bigger hint
Follow one server at a time, top to bottom, and change its state only when one of its stated rules says to. For part 3, look at the ways a 2-way server can leave ESTAB, and check which of them can happen when nobody is on the other end. For part 4, ask when y′ was chosen, and whether anything sent before that moment could contain y′+1.
Answer

1The seven states

2-WAY HANDSHAKE Client Server req_conn(x) delayed in the network req_conn(x) again L1ESTAB acc_conn(x) data flows client closes L2LISTEN …arrives at last L3ESTAB acc_conn(x) no one here 3-WAY HANDSHAKE Client Server SYN(x) delayed in the network SYN(x) again R1SYN_RCVD SYN-ACK(y, ack = x+1) ACK(ack = y+1) R2ESTAB data flows client closes R3LISTEN …arrives at last R4SYN_RCVD SYN-ACK(y′, ack = x+1) ACK(ack = y′+1) …never arrives

The sheet's diagram with the seven states and part 4's missing message filled in.

Both servers see exactly the same arrivals; only their rules differ. When the retransmitted request arrives, the 2-way server's rule sends it straight to ESTAB (L1), while the 3-way server only enters SYN_RCVD (R1) and waits for an ACK carrying y+1, which arrives at R2. Both go back to LISTEN when the client closes (L2, R3). When the delayed copy finally arrives, each server does exactly what it did the first time: ESTAB at L3, SYN_RCVD at R4.

If you wrote ESTAB at R1, you read the 3-way handshake as the 2-way one with an extra message added on the end. The difference comes earlier than that: the 3-way server does not commit to anything on the first message (Figure 3).

2The whole connection

The 2-way server has allocated the connection — its buffers, its sequence-number state, an entry in its connection table — and declared it open, all on the strength of one message that it has no way to date. The 3-way server has recorded x and picked y, and that is all: a small tentative record with a timer on it. It has promised nothing and allocated nothing.

This is the point the question is built on. The 3-way handshake's first gain is not that it recognises the old copy; it is that it refuses to commit until something proves the request is current.

3No — nothing ever releases it

By the rules above, a 2-way server leaves ESTAB only when the client closes the connection, and there is no client to close it. No message is outstanding, so no timer is running. The entry survives until someone restarts the server. This is a half-open connection §3.5.6, and every old duplicate that arrives creates another one. Worse, a delayed copy of the old data(x+1) can now arrive and be accepted as new data, because as far as the server is concerned this is a live connection whose next expected byte is x+1.

If you answered that it times out, you gave the server a timer its rules say it does not have. The question's 2-way server runs no timer in ESTAB, and that single clause is the difference between the two servers.

4ACK(ack = y′+1)

The client. It closed long ago. Nobody at that address is expecting a SYN-ACK, so nobody will answer it; a host that is there but was not expecting one replies with a reset, which ends the attempt sooner still.

The number y′. This is the reason that matters. The server invented y′ at the moment the delayed SYN arrived, so it has never appeared on the network before. No message that was already travelling — however long it was delayed, and however many copies of it exist — can contain y′+1. Old traffic cannot answer the question the server has just asked. That is why the server can safely throw the SYN_RCVD entry away when its timer runs out: it knows exactly what it is waiting for, and that nothing in flight can supply it.

The question drew the client's close as a single ✕. How a TCP connection actually closes, with a FIN from each side, is §3.5.6, and the Timeline worksheet draws it in full.

§3.5 Connection-oriented Transport: TCP · video · video (part 2) · knowledge checks · practice problems

Q3Why y must be new

4 · The three parties in the attack described before part 5

Trusted client address the server accepts Attacker somewhere else Server ① SYN(x), client's address ② SYN-ACK(y, ack = x+1) ③ ACK(ack = ?) — needs y+1 never receives ②

The boxes are three machines on the Internet, and the arrows are the three handshake messages, numbered in the order they are sent. The attacker sends message ① with the trusted client's address written in as its source, so the server takes it for a request from the client. Message ② goes to the address it came "from", which is the trusted client, so the attacker never receives it. The dashed arrow ③ is the message the attacker needs to send next.

The attack succeeds only if the attacker can fill in ③ without ever having seen ②. Part 5 asks which choices of y let it.

Q2 showed that the 3-way handshake survives an old duplicate. This question is about why, and about what would break if one detail changed.

  1. 1

    For each message of the 3-way handshake, what does the side that receives it now know for certain?

    MessageReceived byWhat the receiver now knows for certain
    SYN(x)server
    SYN-ACK(y, ack = x+1)client
    ACK(ack = y+1)server
  2. 2

    Messages 2 and 3 do the same job in opposite directions. Say what that job is in one sentence, and explain why message 1 cannot do it for either side.

  3. 3

    A lazy server always uses y = 100 for every connection instead of picking a new number each time. A client opened a connection to this server earlier, so copies of SYN(x), SYN-ACK(100, ack = x+1) and ACK(ack = 101) have all crossed the network at some point — and the network may still deliver an old copy of any of them.

    Complete the timeline by filling in the boxes.

    (no client) Server LISTEN …old copy of SYN(x) arrives… SYN-ACK(100, ack = x+1) …old copy of ACK(ack = 101) arrives… 1 2
  4. 4

    Three messages were exchanged in part 3, exactly as the protocol requires, and the server still ended up connected to nobody. What property must y have for the 3-way handshake to do its job?

What we mean by an attack

Everything so far went wrong by accident — an old copy turned up at a bad moment. Now add a third machine that is doing it deliberately.

There are three parties: the server; a client the server trusts, perhaps because the server only accepts connections from inside the university; and an attacker somewhere else on the Internet. Neither the client nor the server is misbehaving — the attacker is a stranger to both. What the attacker wants is for the server to open a connection that it believes belongs to the trusted client, so that it can then send data the server would never accept from the attacker's own address.

The attacker can write any source address into the packets it sends, so it puts the trusted client's address on a SYN(x). But it has stolen the address, not the path: the server's reply, SYN-ACK(y, ack = x+1), is delivered to the trusted client, not to the attacker. The attacker never sees y. So the whole attack comes down to one question — can it produce ack = y+1 without having seen message 2? If it can, the server completes the handshake and believes the trusted client is on the other end. If it cannot, the attacker is stuck and the server's SYN_RCVD entry simply times out.

  1. 5

    Which of these choices of y would be safe? For each, say what an attacker or an old copy would have to do to defeat it.

    Choice of ySafe?Why / how it is defeated
    y = x (reuse the client's number)
    A counter the server increases by 1 per connection
    A number the server picks at random
  2. 6

    After message 3 arrives, the server knows the client is live. Does the client know that the server received its ACK? If not, why is the handshake still finished?

Hint
What would you have to have seen in order to write y+1 on a message? And what could you write without having seen anything?
Bigger hint
For part 1, take each message in turn and ask whether an old copy of it, delivered an hour late, would look any different from a fresh one. For part 3, keep the rules exactly as written and check whether 101 equals y+1. For part 5, apply the test from the note to each row: can someone produce ack = y+1 without ever receiving message 2?
Answer

1Only 2 and 3 prove anything about now

MessageThe receiver now knows
SYN(x) → serverThat someone, at some time, asked to open a connection proposing x. Not that they are still there, and not when it was sent: an old copy looks exactly like a fresh request.
SYN-ACK(y, ack = x+1) → clientThat the server is alive right now, is willing, and actually received x — it could not have written x+1 without seeing x. And that the server's number is y.
ACK(ack = y+1) → serverThat the client is alive right now and actually received y: nobody who has not seen this SYN-ACK can produce y+1.

The words "right now" in the second and third rows are the whole difference from the first. They are what an old copy can never supply.

5 · What each handshake message proves

Client Server SYN(x) SYN-ACK(y, ack = x+1) ACK(ack = y+1) ① proposes x; echoes nothing, so it proves nothing about when it was sent ② x+1 proves the server saw x now; y is the server's challenge ③ y+1 proves the client saw y now

The client and server lines, with time running downward and one arrow per message, as in Figure 2. On the right, beside each arrow, is what that message proves to the side that receives it.

Messages ② and ③ each carry back a number the other side chose a moment earlier. Message ① carries back nothing.

2Each proves the other side is alive now

Messages 2 and 3 each prove to one side that the other side is alive at this moment, by echoing back a number that the receiving side has only just chosen. Message 1 echoes nothing; it only proposes x. Nothing in it is something the sender had to have just learned, so the network can hand the server a copy from an hour ago and it will look exactly like a fresh request. A message that carries no evidence of recent contact cannot prove recent contact.

This pattern has a name: challenge and response. One side sends a number the other could not have known in advance, and the other proves it is present by sending it back.

3Box 1: SYN_RCVD · Box 2: ESTAB

(no client) Server LISTEN …old copy of SYN(x) arrives… SYN-ACK(100, ack = x+1) …old copy of ACK(ack = 101) arrives… 1 SYN_RCVD 2 ESTAB

The server follows its rules perfectly. The old SYN puts it in SYN_RCVD, and it replies with y = 100. Then the old ACK(ack = 101) arrives, and 101 is y+1, because y is always 100. The rule says enter ESTAB, so it does. The server is now half-open with no client, exactly like the left half of Q2, despite having run a three-message handshake.

4Fresh and unpredictable

y must be a value that nothing already on the network could contain — one the server has never used before — and that no one else can predict. Its only job is to be evidence of recent contact that cannot be guessed.

If you answered only "different every time", you have the first half. A counter is different every time too, and part 5 shows why that is not enough.

5Only the random y is safe

Choice of ySafe?Why
y = xNox is written in the SYN itself. The attacker chose x, so it already knows x+1; and a delayed copy of an old ACK carries exactly the x+1 that an old SYN would now be challenged with. The challenge contains its own answer.
Counter, +1 per connectionNoBetter than a constant, because old copies no longer match. But an attacker can open one connection of its own, see the current value in the SYN-ACK it receives, and predict the next few. It can then forge message 3 without ever receiving message 2.
RandomYesTo answer the challenge you must actually have received the SYN-ACK, which means being at the address you claim, and being there now.

The test for every row is the one in the note: could someone produce ack = y+1 without ever receiving message 2? For the first two rows the answer is yes. "Safe" here means only that; it does not mean the data is encrypted or that the server knows who it is talking to.

This is not hypothetical. Predictable starting sequence numbers were the basis of real TCP sequence-number prediction attacks, and TCP implementations are now required to choose their initial sequence number unpredictably. Attacks of this kind are Chapter 8.

6No, and it does not need to

The client cannot know its ACK arrived. That ACK could have been lost, and no confirmation can settle it for good, since every confirmation would need a confirmation of its own.

The handshake is finished anyway because nobody needs that knowledge to make progress. If the ACK was lost, the server is still in SYN_RCVD; its timer fires, it retransmits the SYN-ACK, and the client answers again. And any data the client sends will be acknowledged, which settles the matter in passing. The protocol is built so that the only unconfirmed message is one whose loss corrects itself. The authors' climbing analogy is the same shape: "On belay?" — "Belay on." — "Climbing." The climber does not wait for a fourth message confirming that "Climbing" was heard.

If you answered yes, the client knows, ask what message would have told it. The server sends nothing in reply to message 3 as part of the handshake.

§3.5 Connection-oriented Transport: TCP · video · video (part 2) · knowledge checks · practice problems

GW CSCI 4431/6431 Computer Networks · TCP Worksheet

1 / 3