Introduction
Hello! In our last lesson, we explored how TCP guarantees reliable data delivery using sequence numbers, acknowledgments, and retransmission timers. This ensures that every byte sent eventually arrives correctly.
However, reliability is only half the story. Consider this: what happens if the sender is a powerful server on a high-speed connection, and the receiver is a mobile phone on a spotty network? The server could easily send data far faster than the phone can process it. The phone's internal buffer would quickly overflow, forcing it to drop incoming packets. This would trigger a storm of retransmissions, crippling efficiency.
This is where TCP Flow Control comes in. It's the mechanism that allows a receiver to tell a sender, "Slow down! I'm overwhelmed," or "I'm ready for more." In this lesson, we will dive into how TCP implements flow control using a clever technique called the sliding window mechanism.
1. Flow Control vs. Congestion Control
Before we proceed, it's crucial to distinguish between two often-confused terms:
- Flow Control: An end-to-end mechanism that prevents a sender from overwhelming a receiver. It's about matching the sender's speed to the receiver's capacity.
- Congestion Control: A mechanism that prevents a sender from overwhelming the network itself (i.e., the routers and links in between).
Today, our focus is solely on Flow Control—managing the direct relationship between one sender and one receiver.
For a clear definition of flow control and its distinction from congestion control, let's start with a foundational article by Brian Storti.
Read the introductory sections, starting from the beginning and ending just before the 'How it works' heading. Focus on understanding the core purpose of flow control.
2. The Receive Buffer and the Receive Window
The key to flow control lies on the receiver's side. When TCP receives data, it doesn't immediately hand it off to the application (e.g., your web browser). First, it places the data into a temporary storage area called the receive buffer. The application then reads data from this buffer at its own pace.
The problem arises when the sender fills this buffer faster than the application can empty it.
To prevent this, the receiver uses every acknowledgment (ACK) packet it sends to advertise its current state. It does this by setting a value in the TCP header called the Receive Window (or rwnd).
The Receive Window is the amount of available (free) space left in the receive buffer.
This is TCP's feedback mechanism. The receiver is constantly telling the sender exactly how many more bytes it's prepared to accept.

3. The Sliding Window Mechanism
Upon receiving the advertised window size from the receiver, the sender knows its limit. It uses this information to manage a sliding window. This is a conceptual window that covers a portion of the sender's byte stream.
Here's how it works:
- The sender can transmit any bytes that fall within its current window.
- The size of this window is constrained by the receiver's last advertised window size.
- As the receiver acknowledges data, the window "slides" forward, allowing the sender to transmit new data.
This ensures the sender never has more unacknowledged data in transit ("in flight") than the receiver has buffer space.
To visualize this sliding motion, let's watch a short, animated explanation. This video introduces the general concept of a sliding window protocol, which is the foundation for TCP's flow control.
Watch from 02:05 to 07:18. The video begins by explaining the inefficiency of sending only one packet at a time (Stop-and-Wait). Then, it introduces the sliding window as a way to send multiple packets. Pay close attention to how the window moves forward as acknowledgments are received.
The video provides a great high-level view. Now let's connect it specifically to TCP's byte-oriented approach. The sender and receiver maintain several pointers to track the data stream.

The sender must always obey this fundamental rule of flow control:
This invariant guarantees that the sender never transmits more data than the receiver has explicitly reported it can handle.
TCP Flow Control & Sliding Window
The Brian Storti article and the 'Computer Networks: A Systems Approach' textbook both provide excellent, detailed explanations of this process. Let's read the relevant sections from both.
In the Brian Storti article, read the sections 'How it works' and 'The sliding window'. This provides a clear, practical explanation with a great numerical example.
For a more formal and detailed look at the buffer management, let's turn to the textbook.
Read the sections 'Reliable and Ordered Delivery' and 'Flow Control'. Focus on understanding the roles of the various buffer pointers (like LastByteSent and NextByteExpected) and how the AdvertisedWindow is calculated and used by the sender.
4. Handling Extreme Cases: Zero Windows and Deadlocks
What happens if the receiving application stops reading data entirely? The receive buffer will fill up completely.
- The receiver will advertise a
Receive Windowof 0. - When the sender sees this Zero Window advertisement, it must stop sending data (except for special probe packets, which we'll see next).
This creates a potential deadlock. The sender is now waiting for the receiver to advertise a non-zero window, but the receiver will only send a packet (containing the new window size) in response to receiving data. Since the sender isn't allowed to send data, how does it discover that the window has opened up again?
TCP solves this with a Persist Timer. When a sender receives a zero-window update, it starts a timer. When the timer expires, it sends a tiny packet called a Window Probe. This probe contains just one byte of data.
- If the receiver's window is still zero, it will acknowledge the probe and report a window of 0 again. The sender resets its persist timer.
- If the receiver's buffer has cleared, it will accept the 1-byte probe and send an acknowledgment with a new, non-zero window size.
The sender now knows it can resume transmission, and the deadlock is broken.
This entire dynamic—the window shrinking to zero and then opening up again—is not just a theoretical edge case. It's common in real-world network traffic, and you can see it with Wireshark.
How TCP Works - The Receive Window
Let's watch a fantastic video by Chris Greer that uses Wireshark to demonstrate these concepts in a real packet capture.
Watch the video from the beginning to 09:25. It will show you: Where to find the 'Window size value' in the TCP header in Wireshark (00:00 - 01:29). Window Scaling: An essential TCP option used to overcome the 64KB limit of the 16-bit window field, crucial for modern networks (02:00 - 04:15). A Zero-Window Event: You'll see the window size drop, hit zero, and see the sender send 'Zero Window Probe' packets until the window opens up again (04:42 - 09:25).
Conclusion
Today, we've unraveled the elegant mechanism of TCP Flow Control. You learned how TCP prevents a fast sender from overwhelming a slow receiver, ensuring an efficient and orderly flow of data.
Key Takeaways:
- Flow Control is an end-to-end mechanism that matches the sender's rate to the receiver's capacity.
- The receiver uses a receive buffer to store incoming data before the application reads it.
- The Receive Window (
rwnd) is the amount of free space in the receive buffer, which the receiver advertises in every ACK. - The sender uses the
rwndto manage a sliding window, limiting the amount of unacknowledged data in flight toLastByteSent - LastByteAcked <= AdvertisedWindow. - A Zero Window advertisement forces the sender to stop transmitting.
- To prevent deadlock, the sender uses a Persist Timer to periodically send Window Probes, prompting the receiver for a window update.
Preview of the Next Lesson:
We've now covered TCP's connection management, reliability, and flow control. In the next lesson, we'll step back from the packet-level details and look at the connection from the operating system's perspective. You'll learn how to use the netstat command-line tool to view active network connections on your own computer, see their state (e.g., ESTABLISHED, TIME_WAIT), and identify the applications using them.