TCP send window, receive window and how they work

2023.11.16

TCP send window, receive window and how they work

The calculation of the available window is the key to understanding the TCP sliding window. To understand the calculation of the available window, we need to understand three pointers-SND.UNA, SND.NXT and RCV.NXT.

The diagram above is a snapshot taken from the sender's perspective. We can divide the data into 4 groups:

  • Bytes sent and acknowledged (blue)
  • Bytes sent but not yet acknowledged (yellow)
  • Bytes not sent but ready for the receiver to receive (green)
  • Bytes that were not sent and the receiver is not ready to receive them (gray)

Category 3 is also called the available window because this is the window available to the sender.

The sending window consists of yellow and green sections. These bytes have either already been sent or can be sent.

1*OqqxQKu4ZGasXzIlUZ9lyw.png

The available window may be empty when the sender has sent 21-25 bytes and used all bytes in the available window. The sending window remains unchanged.

1*JdTCgvYpVPRDcLyVb8Rwsg.png

When the sender receives an acknowledgment of 16-19 bytes, the sending window slides 4 bytes to the right. There will be an updated available window for the next bytes in the queue.

1*9zFu_scvenahSK6m-khSjw.png

Some definitions can help us better understand the complexities later in this article:

  • SND.WND, represents the sending window
  • SND.UNA, indicates the sending unacknowledged pointer, pointing to the first byte of the sending window
  • SND.NXT means sending the next pointer, pointing to the first byte of the available window

1*IYBc3_OiPWAZ7JCvIaktkA.png

Based on these definitions, we can express the size of the available window with the following formula.

receive window

1*SbgJAvyVKyXYvPLuoBbGtA.png

The receiving window is divided into 3 categories:

  • Bytes received and acknowledged
  • Bytes that have not been received but are allowed to be sent by the sender
  • Bytes that have not been received and may not be allowed to be sent by the sender

Category 2 is called the receive window, also known as RCV.WND.

Similar to the send window, there is a pointer RCV.NXT, which represents the first byte of the receive window.

1*u3KoxvVK-rrM1g4gX6fbZQ.png

The receive window is not static. If the server is running efficiently, the receive window can be expanded. Otherwise, it may shrink.

The receiver communicates its receive window by indicating the size in the window field in the TCP segment header. When the sender receives it, this window size becomes the available window.

Sending and receiving segments takes time. Therefore, the receiving window is not equal to the available window at a specific moment.

Simplified example

Let's simulate a request and response to better understand how sliding windows work.

Two modifications simplify our calculations.

  • We ignored the maximum segment size (MSS). The MSS changes based on the selected network route.
  • We make the receive window equal to the available window and keep it constant throughout the process.

1*sAF4A2TyNeItzw2yK0xI9g.png

Above is a diagram showing an example of 10 steps.

The client requests a resource and the server responds to it with three segments:

  • 50-byte header
  • 80 bytes body part 1
  • 100 bytes body part 2

Each party can be both a sender and a receiver at the same time.

We assume that the client's send window (SND.WND) is 300 bytes and the receive window (RCV.WND) is 150 bytes. Therefore, the server's SND.WND is 150 bytes and the RCV.WND is 300 bytes.

1*cU9TEaEoezDwvw__3G1DFw.png

This is the starting state of the client.

We assume it has previously received 300 bytes from the server, so RCV.NXT points to 301.

Since it hasn't sent anything yet, both SND.UNA and SND.NXT point to 1.

1*IYBc3_OiPWAZ7JCvIaktkA.png

According to this formula, the client's available window size is 1 + 300 - 1 = 300.

1*kfa6ZdhSR_VJggJ2abUSAQ.png

This is the starting state of the server and reflects the state of the other side.

Because it has sent 300 bytes, both SND.UNA and SND.NXT point to 301.

Since the client has not sent any requests yet, RCV.NXT points to 1.

The server's available window is 301 + 150 - 301 = 150.

Now, step 1 begins.

The client sent the first 100 bytes of the request. At this moment, the window changes.

  • These 100 bytes have been sent but not acknowledged yet. Therefore, SND.NXT slides 100 bytes to the right.
  • The other pointers remain unchanged.

The available window becomes 1 + 300 - 101 = 200.

1*ug0laVIMWQ3HGG-kPjZ0KA.png

In step 2, we focused on the server.

  • When the server receives the request, RCV.NXT slides 100 bytes to the right.
  • Then a 50 byte response with ACK was sent. These 50 bytes were sent but not acknowledged, so SND.NXT is shifted 50 bytes to the right.
  • SND.UNA remains unchanged.

The available window becomes 301 + 150 - 351 = 100.

1*GAZqLwbVGj2yqUnm5DyI4w.png

Move to client.

  • When the client receives a 50-byte response, RCV.NXT slides 50 bytes to the right.
  • When it receives the 100-byte ACK sent previously, SND.UNA slides to the right.
  • Since the client didn't send any data, SND.NXT remains unchanged.

The available window becomes 101 + 300 - 101 = 300.

1*50UitYxS9XW3N4XV2Z7tOg.png

Move to one side of the server again.

The available window is 100 bytes. The server can send segments of 80 bytes.

  • SND.NXT slid 80 bytes to the right.
  • Since the first 50 bytes have not yet been acknowledged, SND.UNA remains unchanged.
  • Since the server did not receive any data, RCV.NXT remains unchanged.

The available window becomes 301 + 150 - 431 = 20.

1*soNJeyvqRj0zqDDrtBL9Fg.png

The client received the first part of the file and sent an ACK immediately.

  • When the client receives 80 bytes of data, RCV.NXT slides to the right.
  • The other pointers remain unchanged.

The available window remains at 300.

1*QJKwuY3HvslR9601ZRWCxA.png

At this point, the server receives the ACK when sending step 2.

  • When the server sends a 50-byte response, SND.UNA slides 50 bytes to the right.
  • The other pointers remain unchanged.

1*thuJ7lCYqreqxsL8nMz_ag.png

In step 4, the server sent the first 80-byte portion of the file and again received an ACK.

  • SND.UNA (sequence number acknowledged) is shifted 80 bytes to the right.
  • The other pointers remain unchanged.

The calculation of the available window becomes 431 + 150 - 431 = 150.

1*8sS5S0OkW0I2Vbp40nkkZQ.png

In step 8, the server sends the second part of the file, which is 100 bytes in total.

  • SND.NXT (the next sequence number to be sent) is shifted 100 bytes to the right.
  • The other pointers remain unchanged.

The calculation of the available window becomes 431 + 150 - 531 = 50.

1*qXP9BCX80vPpkplc5utP6Q.png

Next, it's the client's turn.

  • RCV.NXT (next sequence number to receive) is shifted 100 bytes to the right after the client receives 100 bytes.
  • The other pointers remain unchanged.

The available windows remain unchanged.

1*LkQ7tG-_1XQROjOZ3vTC9g.png

Finally, the server receives the ACK for the previous response.

  • SND.UNA is shifted 100 bytes to the right.
  • The other pointers remain unchanged.

The calculation of the available window becomes 531 + 150 - 531 = 150.

When the window changes

Before, we assumed that the sending window and receiving window remained unchanged. But in real situations, this assumption is incorrect, because the bytes in both windows exist in the operating system buffer, and the free space in the buffer can be adjusted. When our application cannot read the bytes in the buffer quickly, the available space decreases.

Let's look at what happens when a window changes and how it affects the available windows.

1*qyjkUdkAdsfrkRkqVlPClw.png

For simplicity, this example focuses on the windows available to the client. In this example, the client is always the sender and the server is the receiver.

1*u3KoxvVK-rrM1g4gX6fbZQ.png

When the server sends the ACK, it also includes the updated window size.

1*pkiC_TWGpIZF3aSPOz6lcA.png

Initially, the client sends a 150-byte request.

  • These 150 bytes have been sent but not yet acknowledged.
  • The available window is reduced to 150 bytes.
  • The send window remains at 300 bytes.

1*zs4VuHChJJ-7vWFmXyr8Ug.png

When the server receives the request, the application reads the first 50 bytes and the remaining 100 bytes are still in the buffer, taking up 100 bytes of free space from the receive window. Therefore, the receive window is reduced to 200 bytes.

Next, the server sends an ACK with an updated 200-byte receive window.

1*SZDl6q22CB6kzY3P-CCHFA.png

The client receives the ACK and updates its sending window size to 200.

At this point, the available window is the same as the send window because all 150 bytes have been acknowledged.

1*6gKYyaDUdOQSEGfHh6SWdA.png

Again, the client sends another 200-byte request, using all the available space in the available window.

1*uJiRzHmdV4kT8lPW62bz0g.png

After the server has received these 200 bytes, the application is still running slowly, reading only 70 bytes in total, leaving 280 bytes in the buffer. This causes the receive window to shrink again, now only 20 bytes remain.

In the ACK message, the server shares the updated window size with the client.

1*xnUjR-R45hPoGO7qhvCHKg.png

Again, the client updates its sending window to 20 bytes after receiving the ACK, and the available window also becomes 20 bytes.

In this case, if there are no more messages from the server, the client will stop sending requests larger than 20 bytes until another window update is received in a subsequent message.

So if no more messages come from the server, are we stuck with the 20 byte available window?

Won't. To avoid this, the client's TCP periodically checks the window size.

Once more space is freed up,

The available window will expand and more data can be sent.

main content

  • The calculation of the available window is the key to understanding TCP sliding windows.
  • To understand the calculation of the available window, we need to understand 3 pointers - SND.UNA, SND.NXT and RCV.NXT.
  • Assuming that the window size never changes helps us understand the entire process.