SubnetLayer

Zero-Window Probes

RFC 1122 §4.2.2.17 · how a stalled connection stays alive

Step 1 of 2 — understand the idea. Read this first and the packet trace will confirm what you already expect, instead of teaching you two things at once.

What you'll be able to do

Before this lesson — it builds directly on:
A receiver whose buffer is full advertises a window of zero, and the sender correctly stops. Later the application reads some data, space frees up, and the receiver sends a window update saying 'you may resume'. But that update is a pure acknowledgement carrying no data — and TCP never retransmits those, because nothing acknowledges them. If it is lost, the sender waits forever for permission that will never arrive, and the receiver waits forever for data the sender will never send. Both sides are behaving perfectly and the connection is dead. The fix is to make the SENDER responsible: it periodically pokes the receiver to ask whether anything has changed.

✗ Common misunderstanding: The window field advertises how fast the link is.

Why that's wrong: It advertises free space in the receiver's buffer, in bytes. It says nothing about the network between the two hosts.

Correct model: Window = free memory at the receiver. Speed is a consequence (window ÷ round-trip time), not the meaning.

The packets prove it: In the sliding-window trace the window falls to 0 while the link is completely idle — the receiver's application simply stopped reading.

Watch these fields in the lab: tcp.windowSize

The design question here is worth generalising: when two parties are both waiting, which one should be responsible for breaking the tie? TCP's answer is the side with something to lose. The sender has undelivered data and a user waiting on it, so the sender is the one who must keep asking. The receiver's window update is treated as a helpful optimisation — if it arrives, things resume immediately; if it's lost, the probe catches it a moment later. Building the recovery around the party that cares is why this failure mode simply doesn't happen in practice.
Knocking on a door periodically, rather than waiting to be called
"not now"
a zero window
knocking again after a while
a persist probe
the message "come in" going astray
a lost window update

Where it breaks down: A person who keeps knocking is being rude. A sender that stopped would be broken — and unlike a visitor, it cannot phone ahead or try another door, because the connection is the only channel it has.

Buffers, the window, and bytes in flightThe sender holds data in a send buffer. Data that has been sent but not yet acknowledged is in flight. The receiver holds arrived data in a receive buffer until the application reads it, and advertises the remaining free space as the receive window.Sendersend buffer (queued to send)In flightsent, not yet acknowledgedReceiverarrived,unreadfreespaceadvertised window = free spaceRule: bytes in flight must never exceed the advertised window.App reads slowly → unread grows → window shrinks → sender must slow down.Window reaches 0 → sender stops completely until an update arrives.
The advertised window is FREE SPACE in the receiver's buffer — not bandwidth, not speed. It shrinks as data waits unread and reopens when the application reads.

Watch these fields in the lab: tcp.windowSize

✓ Concept check — before you open the packets

These test the idea, not the trace. You should be able to answer them from the explanation above.

Why does the SENDER probe, rather than the receiver simply retransmitting its window update?

A capture shows a server repeatedly advertising Win=0 over several seconds. What should you investigate first?

Now that you understand the concept, observe how it appears in the packet exchange.

The lab runs a real simulated capture — pause, step, click any packet, and inspect every byte.