Introduction
A TCP receiver places arriving bytes in a receive buffer, from which the application reads them when it chooses. If the sender sends faster than the application reads, the buffer fills and further bytes would be lost. Flow control prevents this: in every segment the receiver advertises a receive window (rwnd), modelled here as free receive-buffer space (implementation window-allocation policies can differ), and the sender uses the latest accepted window to limit new transmissions. A reduced rwnd or cwnd can temporarily be smaller than data already in flight; it does not withdraw already-sent bytes.
This is a sliding-window protocol (Sliding Window Protocols) with two differences: the window counts bytes, not frames, and its size changes during the connection as the receiver's buffer fills and empties. Flow control protects the receiver; congestion control (TCP Congestion Control) protects the network, and the sender obeys the smaller of the two windows.
The 16-bit window and 32-bit sequence number also have limits on fast links: the window scale option and sequence-number wraparound.
Prerequisites
- Transport Layer: UDP and TCP Basics: sequence and acknowledgement numbers, the window field.
Core concepts
The receiver's side
For this simplified buffer model, assume all received data is in order and no out-of-order bytes are buffered. In general, actual free buffer space is RcvBuffer minus all unread buffered bytes, including out-of-order data; this is not a complete implementation window-allocation policy. With buffer size RcvBuffer, the last byte the application has read LastByteRead, and the last byte received in order LastByteRcvd:
The receiver puts rwnd in the window field of every segment it sends, together with the ACK number.
The sender's side
The sender keeps
where in this simplified in-order model. Without congestion control, omit cwnd and use . This is permission for new data, not an invariant on previously transmitted data after a window reduction. The window's left edge advances when ACKs arrive; its advertised right edge is .
Zero window and the persist timer
When rwnd = 0 the sender stops. The receiver will announce new space in a window update, but that segment carries no data and is not acknowledged; if it were lost both sides would wait forever. So a sender facing a zero window starts a persist timer and, when it fires, sends a window probe (one byte, or a segment the receiver must answer) to draw out the current window.
Silly window syndrome
If the application reads one byte at a time and the receiver advertises every freed byte, the sender sends one-byte segments, each with 40 bytes of headers. Two fixes:
- Receiver side (Clark's solution): do not advertise a small window; advertise 0 until the free space is at least .
- Sender side (Nagle's algorithm): while any data is unacknowledged, hold back small segments; send them together when the ACK arrives or a full MSS has accumulated. Interactive applications that need each keystroke at once may switch it off.
Delayed ACKs. A receiver may also wait before acknowledging, so one ACK can cover two segments and carry a window update or reply data; RFC 1122 requires the delay to stay under 0.5 seconds and an ACK for at least every second full-sized segment.

Mathematical explanation: limits of the header fields
Throughput bound of the window
At most one window is delivered per round-trip time, so
The 16-bit window field allows at most 65,535 bytes, so without scaling a connection with RTT 100 ms cannot exceed Mbps, however fast the link. To keep a link busy the window must be at least the bandwidth-delay product (Performance Metrics).
Window scaling
The window scale option (RFC 7323), sent on the SYN, gives a shift count between 0 and 14; the true window is the 16-bit field times . The largest window is about bytes (1 GiB). The limit 14 keeps the window below , which leaves room in the sequence space for old and new data to be told apart. To support window , the smallest shift is the least with .
Sequence-number wraparound
Sequence numbers are 32-bit byte counts, so they repeat after bytes. At bandwidth bit/s the wrap time is
If is less than the maximum segment lifetime, an old duplicate could carry a sequence number that is valid again. RFC 9293 takes MSL as 2 minutes; with TCP timestamps, PAWS (protection against wrapped sequences, RFC 7323) rejects such old segments.
| Bandwidth | Wrap time |
|---|---|
| 10 Mbps | about 3436 s (57 min) |
| 100 Mbps | about 344 s |
| 1 Gbps | about 34.4 s |
| 10 Gbps | about 3.4 s |
The inverse question: for bandwidth and lifetime , the sequence field needs at least bits to count every byte sent in seconds without repeating.
Worked examples
Example 1: a buffer trace
RcvBuffer = 4096 bytes, MSS = 1024 bytes, Clark's rule in use (threshold ).
| Step | Event | Buffered | Free | Advertised rwnd |
|---|---|---|---|---|
| 0 | Connection opens | 0 | 4096 | 4096 |
| 1 | 3 segments arrive (3072 bytes) | 3072 | 1024 | 1024 |
| 2 | Application reads 1024 | 2048 | 2048 | 2048 |
| 3 | 2 segments arrive (2048 bytes) | 4096 | 0 | 0 (sender stops; persist timer) |
| 4 | Application reads 1 byte | 4095 | 1 | 0 (Clark: 1 < 1024); a naive receiver would say 1 |
| 5 | Application reads 1023 more | 3072 | 1024 | 1024 |
Between steps 3 and 5 the sender's persist timer may fire; the probe is answered with the current window (0 at step 4).
Example 2: how much may be sent
LastByteAcked = 5000, LastByteSent = 7000, the latest rwnd = 3000, and cwnd = 4000. The bound is bytes outstanding; 2000 are outstanding, so 1000 more may be sent now: bytes 7001 to 8000.
Example 3: window needed and scale factor
A path with 1 Gbps and RTT 100 ms has bandwidth-delay product bytes. Without scaling the window is at most 65,535 bytes, so throughput is at most about 5.24 Mbps, about 0.5% of the link. The least shift with is ( gives 8,388,480; gives 16,776,960).
Example 4: bits for the sequence number
A 1 Gbps link and a segment lifetime of 60 s: bytes can be sent in one lifetime. , so at least 33 bits are needed; TCP's 32 bits wrap in 34.4 s at this rate, which is why PAWS exists.
Example 5: Nagle's algorithm
A user types a character every 70 ms (at 0, 70, ..., 980 ms; 15 characters) over a connection with RTT 200 ms. Without Nagle, 15 one-byte segments are sent. With Nagle, the first character goes at once; each later segment leaves when the previous one is acknowledged:
| Sent at (ms) | 0 | 200 | 400 | 600 | 800 | 1000 |
|---|---|---|---|---|---|---|
| Characters | 1 | 2 | 3 | 3 | 3 | 3 |
Six segments instead of fifteen.
Example 6: the fastest rate without wraparound
With MSL 2 minutes, sequence numbers must not wrap within 120 s, so at most bytes may be sent in 120 s:
about 286 Mbps. Faster connections rely on PAWS; at 1 Gbps the sequence space wraps in about 34.36 s.
Important properties and observations
- Byte-based, variable window. Unlike link-layer sliding windows, the window is in bytes and set by the receiver segment by segment.
- The receiver controls the right edge. ACKs move the left edge; reading by the application moves the right edge.
- A receiver should not shrink the window (move the right edge back); RFC 9293 strongly discourages it.
- Flow control is end to end. Routers take no part; congestion control deals with the network.
Common misconceptions.
- "rwnd is the buffer size." It is the free part of the buffer.
- "Flow control and congestion control are the same." One protects the receiver (rwnd), the other the network (cwnd); the sender uses the minimum.
- "A zero window ends the connection." The sender waits and probes.
- "Window scaling changes the sequence-number size." Sequence numbers stay 32 bits; only the window field is scaled.
GATE examination perspective
- rwnd arithmetic. Buffer minus buffered bytes; new-send allowance = ; a reduction may leave older data above the new window.
- Maximum throughput. Window / RTT; check the 65,535-byte limit without scaling.
- Scale factor. Least with bandwidth-delay product.
- Wraparound. seconds; compare with the lifetime; or bits = ; or the largest rate for lifetime .
- Silly window, Nagle, Clark, persist timer. Know which side each mechanism runs on.
Summary
Sources
- A. S. Tanenbaum, D. J. Wetherall, Computer Networks, 5th ed., Pearson, 2011: Sections 6.5.8 (TCP Sliding Window) and 6.6.6 (Protocols for Long Fat Networks).
- J. F. Kurose, K. W. Ross, Computer Networking: A Top-Down Approach, 8th ed., Pearson, 2021: Section 3.5.5 (Flow Control).
- B. A. Forouzan, Data Communications and Networking, 5th ed., McGraw-Hill, 2013: Chapter 24 (Internet Transport-Layer Protocols).
- D. Borman, B. Braden, V. Jacobson, R. Scheffenegger (Ed.), RFC 7323, TCP Extensions for High Performance, 2014, Sections 1.2 (TCP Reliability: wrapped sequence numbers), 2 (TCP Window Scale Option, shift limit 14) and 5 (PAWS), (consulted 2026-11-11).
- R. Braden (Ed.), RFC 1122, Requirements for Internet Hosts: Communication Layers, 1989, Sections 4.2.3.2 (When to Send an ACK Segment), 4.2.3.3 (When to Send a Window Update) and 4.2.3.4 (When to Send Data: Nagle), (consulted 2026-11-11).
- W. Eddy (Ed.), RFC 9293, Transmission Control Protocol (TCP), 2022, Sections 3.4 (Sequence Numbers: MSL of 2 minutes), 3.7.4 (Nagle Algorithm) and 3.8.6 (Managing the Window), (consulted 2026-11-11).