TCP and UDP/TCP, step by step/Flow control: the receiver's room
Lesson 8 of 12 · in 3D and VR

Flow control: the receiver's room

Every TCP acknowledgement carries a second number, the window, which is how many more bytes the receiver has room for. It protects the receiver's buffer and says nothing about the network. A window of zero stops the sender until the receiver opens it again.

Lonely BinaryUpdated 2026-10-014 min readNo board required

View it in VR

Lesson 8 of the TCP and UDP course opens in a VR headset, on a table in front of you, and a voice starts three seconds after you arrive. Type this short address into the browser on a headset such as Meta Quest or Apple Vision Pro, and press Enter VR. No headset? Press Start the lesson: the same lesson, full screen.

learn.lonelybinary.com/vr/tcp-udp/8

Next to the acknowledgement number, each TCP segment carries a window. It counts, from the acknowledged byte on, how many more bytes the receiver will accept. The sender must not have more than that outstanding. If the window is 500 and the acknowledgement is 800, the sender may send bytes 800 up to but not including 1300, until a newer acknowledgement says otherwise.

Room in the buffer

The window is the free part of the receiver's buffer. A byte that has arrived in order and not yet been read by the program takes room, and a byte the program reads gives it back. So the window moves with the reader, and not with the network: a program that reads slowly, or has stopped reading, makes the window shrink on every acknowledgement, and the sender slows to the pace of the reader without any error.

A window of zero

When the buffer is full, the receiver advertises zero. The sender stops, and it is not waiting for a lost acknowledgement. It has been told there is no room. It does not simply wait for news, because the update that reopens the window might itself be lost. So it sends small probes now and then, and the receiver answers each one with its current window. In the bench the probe is an empty segment, and in real stacks it is a very small segment. When the program reads and room opens, the receiver sends the new window, and the sender goes on.

How big a window can be

The window field is 16 bits, so without the window scale option of RFC 7323 it cannot say more than 65,535 bytes. With the option a window can reach a gibibyte, 2^30 bytes. The option is agreed once, in the handshake.

An ESP32 keeps its buffers small on purpose, to save RAM. In ESP-IDF the default TCP window is 5760 bytes, which is four full segments of 1440, and window scaling is off by default, so a larger buffer could not be advertised past 65,535 bytes anyway. Since a sender cannot have more than a window in flight, the rate it can reach is at most the window divided by the round trip. With 5760 bytes and a round trip of 50 ms that is about 115 kilobytes a second, however fast the link is. That is arithmetic, not a measurement. The Arduino core sets its own sizes, and this page gives no number for its window.

What it does not do

The window says how much the receiver can hold. It says nothing about the desks in between. A sender with a wide open window can still send more than a router can pass, and the next lesson is about what happens then.

Common mistakes

  • Not reading a socket and wondering why the other side stalls. Unread bytes fill the buffer, the window goes to zero, and the sender stops with no error on either side.
  • Taking a bigger buffer for a better link. A larger window allows more in flight, and it does nothing about a path that is already full.
  • Reading a window of zero as a failed connection. The sender is waiting for room, and it asks again by itself.

Edit this page — content/fundamentals/tcp-udp/receiver-window.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Fundamentals on the forum →