G27
Self-checkedTier 1 7 min readcn.tcp-flow-control

TCP flow control

How TCP stops a fast sender from overflowing a slow receiver: the receive buffer and the advertised receive window rwnd = RcvBuffer - (LastByteRcvd - LastByteRead), the rule LastByteSent - LastByteAcked <= rwnd, the window field in every acknowledgement, the zero-window probe, the silly window syndrome, the throughput limit rwnd / RTT of a 16-bit window and the window scale option, and the difference from congestion control; a round-based simulation checks that the buffer never overflows and that the long-run rate is the slower of the application and the buffer per round.

Why it exists

The receiving application reads data from TCP's receive buffer at its own speed. If the sender transmits faster than the application reads, the buffer overflows and data are dropped. Flow control lets the receiver tell the sender how much room is left. It is about protecting the receiver; protecting the network is congestion control, a separate mechanism (congestion control).

Prerequisites

You need the TCP segment, its window field and the byte numbering (TCP basics), and the sliding window idea (sliding window protocols).

Precise definitions

The receiver has a buffer of size RcvBuffer\text{RcvBuffer}. Let LastByteRcvd\text{LastByteRcvd} be the number of the last byte that arrived in order, and LastByteRead\text{LastByteRead} the number of the last byte the application has taken out. The data waiting in the buffer are LastByteRcvd−LastByteRead\text{LastByteRcvd} - \text{LastByteRead}, and the free space the receiver advertises in the window field of every segment it sends (including acknowledgements) is the receive window:

rwnd=RcvBuffer−(LastByteRcvd−LastByteRead).\text{rwnd} = \text{RcvBuffer} - (\text{LastByteRcvd} - \text{LastByteRead}).

The sender keeps the number of bytes that are outstanding (sent, not yet acknowledged) no greater than the latest rwnd:

LastByteSent−LastByteAcked  ≤  rwnd.\text{LastByteSent} - \text{LastByteAcked} \;\le\; \text{rwnd}.

Hence the receive buffer cannot overflow. The window advertised is a count of bytes, counted from the acknowledgement number.

Zero window. If rwnd =0= 0 the sender stops. Since no acknowledgement will arrive to reopen the window if the receiver sends nothing more, the sender sends tiny probe segments (one byte) periodically; the reply carries the current window (quoted).

Window limit. The window field is 16 bits: rwnd≤65 535\text{rwnd} \le 65\,535 bytes. For fast long links the window scale option (negotiated in the handshake) multiplies the field by 2s2^s (quoted).

How it works

A receiver that reads slowly

Flow control: receive buffer 4000 bytes, application reads 1000 bytes per round: start

Computed by a script, not typed
round (one RTT)advertised windowbytes sentbuffer after arrivalbuffer after the application reads
round 1
round 2
round 3
round 4
round 5
round 6
round 7

Step 0

The sender may not have more than the advertised window outstanding; the window advertised in round r+1 depends on how much the application has read. 10 000 bytes to send, MSS 1000.

0 / 7
computed by script: protocols are simulated slot by slot or round by round, sequence numbers use 32-bit arithmetic. python3 scripts/gen-cn4-traces.py

The receive buffer is 40004000 bytes and the application reads only 10001000 bytes per round trip. The sender starts with an advertised window of 40004000 bytes and sends 40004000 at once; the application reads 10001000, so the next advertised window is 10001000: the sender is slowed down to the speed of the application. In steady state each round sends 10001000 bytes, the buffer stays almost full (30003000 to 40004000 bytes), and the transfer of 10 00010\,000 bytes needs 77 rounds. The sender's average rate is the application's read rate, not the link rate: the receiver controls the speed.

Throughput limit of a window

At most one window of data can be sent per round-trip time, so

throughput  ≤  rwndRTT.\text{throughput} \;\le\; \frac{\text{rwnd}}{\text{RTT}} .

A link can be filled only if the window is at least the bandwidth-delay product (performance metrics).

Throughput limit of a 16-bit window: start

Computed by a script, not typed
round-trip timemaximum throughput with 65 535 byteswindow needed for 1 Gbpswindow scale shift needed
RTT 10 ms
RTT 50 ms
RTT 100 ms
RTT 200 ms

Step 0

Throughput ≤ window / RTT. The window field of the TCP header has 16 bits.

0 / 4
computed by script: protocols are simulated slot by slot or round by round, sequence numbers use 32-bit arithmetic. python3 scripts/gen-cn4-traces.py

With the maximum 16-bit window of 65 53565\,535 bytes and a round-trip time of 100100 ms the throughput cannot exceed 65535×8/0.1=5.2465535 \times 8 / 0.1 = 5.24 Mbps, even on a 11 Gbps link. A 11 Gbps link with 100100 ms RTT has a bandwidth-delay product of 12.512.5 MB, which needs a window about 282^8 times larger than the field allows: that is what the window scale option provides.

Silly window syndrome (quoted)

If the receiver advertises every tiny amount of freed space (for example 11 byte) and the sender sends a tiny segment each time, the connection exchanges 4040-byte headers for 11 byte of data. The remedies: the receiver does not advertise a window increase until it is at least one MSS or half its buffer (Clark's solution), and the sender waits until it can send a full segment (Nagle's algorithm).

Flow control against congestion control

flow controlcongestion control
protectsthe receiver's bufferthe network (routers)
windowrwnd, advertised by the receiver in every segmentcwnd, computed by the sender
informationexplicit, in the headerinferred from losses and delays

The sender uses the smaller of the two: LastByteSent−LastByteAcked≤min⁡(cwnd,rwnd)\text{LastByteSent} - \text{LastByteAcked} \le \min(\text{cwnd}, \text{rwnd}).

Worked examples

EX 1Advertised window

Easy

Receive buffer 80008000 bytes. 50005000 bytes have arrived in order and the application has read 20002000 of them. Data in the buffer: 30003000. rwnd=8000−3000=5000\text{rwnd} = 8000 - 3000 = 5000.

EX 2Throughput limit

Medium

Window 6464 KB =65 536= 65\,536 bytes, RTT 5050 ms: at most 65536×8/0.05=10.4965536 \times 8 / 0.05 = 10.49 Mbps. For a link of 100100 Mbps and RTT 5050 ms the bandwidth-delay product is 625 000625\,000 bytes; the window should be about 1010 times larger, so the scale shift would be 44 (24=162^4 = 16).

EX 3A slow application

Medium

Buffer 40004000, MSS 10001000, the application reads 10001000 bytes per round trip. Round 1: window 40004000, send 40004000, after reading 30003000 remain, so the new window is 10001000. Rounds 22 onwards: window 10001000, send 10001000, read 10001000: the long-run rate is 10001000 bytes per RTT, the application's rate.

EX 4Typical questions

GATE level

(a) "Which field implements TCP flow control?" The window field (receive window). (b) "What stops a sender if rwnd =0= 0?" It waits (and sends probes) until a segment reopens the window. (c) "Effective window of the sender with cwnd =20= 20 KB and rwnd =12= 12 KB?" min⁡=12\min = 12 KB. (d) "Maximum throughput with a 1616-bit window and RTT =20= 20 ms?" 65535×8/0.02=26.265535 \times 8 / 0.02 = 26.2 Mbps. (e) "Time to send a file with a window of WW bytes and RTT RR over a fast link?" About ⌈size/W⌉×R\lceil \text{size}/W \rceil \times R.

Cheat box

Cheat box

  • rwnd == RcvBuffer −- (LastByteRcvd −- LastByteRead); advertised in every segment.
  • Sender: LastByteSent −- LastByteAcked ≤\le rwnd (and ≤\le cwnd).
  • Throughput ≤\le rwnd / RTT; 16-bit window ≤65 535\le 65\,535 bytes; window scale option for more.
  • rwnd =0= 0: stop and probe. Silly window: avoid tiny windows and segments.
  • Flow control protects the receiver; congestion control the network.

Traps and GATE patterns

Connections

The advertised window is the window of the sliding window protocol, carried in TCP (sliding window protocols, TCP basics); the sender's other limit comes from congestion control. The buffer-and-reader situation is the producer-consumer problem of the operating system (classic synchronization problems).

PYQs

2 previous year questions from your book. I re-solved each one myself (1 by running or simulating, 1 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2015 · MCQQ55 · page 556 of the book
Assume that the bandwidth for a TCP connection is
1048560 bits/sec. Let α be the value of RTT in
milliseconds (rounded off to the nearest integer) after
which the TCP window scale option is needed. Let β
be the maximum possible window size with window
scale option. Then the values of α and β are:
  • (a)63 milliseconds 65535 × 214
  • (b)63 milliseconds 65535 × 216
  • (c)500 milliseconds 65535 × 214
  • (d)500 milliseconds 65535 × 216
GATE 2015 · MCQQ59 · page 557 of the book
Suppose two hosts use a TCP connection to transfer
a large file. Which of the following statements
is/are FALSE with respect to the TCP connection?
1. If the sequence number of a segment is m, then
the sequence number of the subsequent segment
is always m+1.
2. If the estimated round trip time at any given
point of time is t sec, the value of the
retransmission timeout is always set to greater
than or equal to t sec.
3. The size of the advertised window never
changes during the course of the TCP
connection.
4. The number of unacknowledged bytes at the
sender is always less than or equal to the
advertised window.
  • (a)3 only
  • (b)1 and 3 only
  • (c)1 and 4 only
  • (d)2 and 4 only

Self-check

Question 1

RcvBuffer =10= 10 KB, 66 KB in the buffer unread. What does the receiver advertise?

Show answer

44 KB.

Question 2

Why can a 1616-bit window not fill a 11 Gbps, 100100 ms path?

Show answer

The bandwidth-delay product is 12.512.5 MB, far above 65 53565\,535 bytes; only one window per RTT can be sent, giving 5.245.24 Mbps.

Question 3

The advertised window is 00. How does the sender learn that it has reopened?

Show answer

It sends periodic one-byte probe segments; the acknowledgement of a probe carries the current window.

Revision card

One-screen revision

  • rwnd = free buffer space, in every ACK; outstanding ≤min⁡(rwnd,cwnd)\le \min(\text{rwnd}, \text{cwnd}).
  • Throughput ≤\le rwnd / RTT; scale option beyond 65 53565\,535.
  • Zero window: probe. Silly window: wait for a full segment / half a buffer.

References

  • ·Kurose, Ross, Computer Networking: A Top-Down Approach (8th edition), Chapter 3, Section 3.5.5 (Flow control)
  • ·Tanenbaum, Wetherall, Computer Networks (5th edition), Chapter 6, Section 6.5.9 (TCP sliding window)
  • ·Forouzan, Data Communications and Networking (5th edition), Chapter 24, Section 24.3 (Flow control)

Verification

scripts/enum-checks/cn_tcp_check.py: the round-based simulation of scripts/cn_tcp.py (flow_sim; one round = one round trip, the sender sends at most the advertised window in whole segments, the application reads a fixed number of bytes per round, the new window is the free buffer space) was run on 500 random cases (buffers 4000 to 65535 bytes, MSS 500 to 1460, read rates 200 to 20000 bytes per round, transfers up to 400 000 bytes): all bytes are delivered, the buffer never exceeds its size, the bytes sent in a round never exceed the advertised window, and in the steady state the bytes sent per round equal min(read rate, buffer size) within one MSS. The throughput limit 65535 x 8 / RTT is arithmetic. MODEL: the receiver advertises the free space after the application's read of that round; sender and receiver proceed in lock step per round trip; real TCP overlaps rounds, delays acknowledgements and updates the window on every ACK. QUOTED, not verified here: the silly window syndrome and its remedies (Clark's receiver rule, Nagle's algorithm), the zero window probe, the window scale option (shift count up to 14, windows up to about 1 GB), the statement that the sender is also limited by the congestion window (min of the two), and the fields LastByteRead / LastByteRcvd of the textbook. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (CRC remainders, binomial tail, checksums); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose). No defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never