TCP Silly Window Syndrome

In the topic describing TCP‘s Maximum Segment Size (MSS) parameter, I explained the trade-off in determining the optimal size of TCP segments. If segments are too large, we risk having them become fragmented at the IP level. Too small, and we get greatly reduced performance because we are sending a small amount of data in a segment with at least 40 bytes of header overhead. We also use up valuable processing time that is required to handle each of these small segments.

The MSS parameter ensures that we don‘t send segments that are too large—TCP is not allowed to create a segment larger than the MSS. Unfortunately, the basic sliding windows mechanism doesn‘t provide any minimum size of segment that can be transmitted. In fact, not only is itpossible for a device to send very small, inefficient segments, the simplest implementation of flow control using unrestricted window size adjustmentsensures that under conditions of heavy load, window size will become small, leading to significant performance reduction!

How Silly Window Syndrome Occurs

To see how this can happen, let‘s consider an example that is a variation on the one we’ve been using so far in this section. We‘ll assume the MSS is 360 and a client/server pair where again, the server‘s initial receive window is set to this same value, 360. This means the client can send a “full-sized” segment to the server. As long as the server can keep removing the data from the buffer as fast as the client sends it, we should have no problem. (In reality the buffer size would normally be larger than the MSS.)

Now, imagine that instead, the server is bogged down for whatever reason while the client needs to send it a great deal of data. For simplicity, let‘s say that the server is only able to remove 1 byte of data from the buffer for every 3 it receives. Let‘s say it also removes 40 additional bytes from the buffer during the time it takes for the next client‘s segment to arrive. Here‘s what will happen:

  1. The client‘s send window is 360, and it has lots of data to send. It immediately sends a 360 byte segment to the server. This uses up its entire send window.
  2. When the server gets this segment it acknowledges it. However, it can only remove 120 bytes so the server reduces the window size from 360 to 120. It sends this in the Window field of the acknowledgment.
  3. The client receives an acknowledgment of 360 bytes, and sees that the window size has been reduced to 120. It wants to send its data as soon as possible, so it sends off a 120 byte segment.
  4. The server has removed 40 more bytes from the buffer by the time the 120-byte segment arrives. The buffer thus contains 200 bytes (240 from the first segment, less the 40 removed). The server is able to immediately process one-third of those 120 bytes, or 40 bytes. This means 80 bytes are added to the 200 that already remain in the buffer, so 280 bytes are used up. The server must reduce the window size to 80 bytes.
  5. The client will see this reduced window size and send an 80-byte segment.
  6. The server started with 280 bytes and removed 40 to yield 240 bytes left. It receives 80 bytes from the client, removes one third, so 53 are added to the buffer, which becomes 293 bytes. It reduces the window size to 67 bytes (360-293).

This process, which is illustrated in Figure 228, will continue for many rounds, with the window size getting smaller and smaller, especially if the server gets even more overloaded. Its rate of clearing the buffer may decrease even more, and the window may close entirely.

Figure 228: TCP “Silly Window Syndrome”

This diagram shows one example of how the phenomenon known as TCP silly window syndrome can arise. The client is trying to send data as fast as possible to the server, which is very busy and cannot clear its buffers promptly. Each time the client sends data the server reduces its receive window. The size of the messages the client sends shrinks until it is only sending very small, inefficient segments.

(Note that in this diagram I have shown the server’s buffer fixed in position, rather than sliding to the right as in the other diagrams in this section. This way you can see the receive window decreasing in size more easily.

Let‘s suppose this happens. Now, eventually, the server will remove some of the data from this buffer. Let‘s say it removes 40 bytes by the time the first closed-window “probe” from the client arrives. The server then reopens the window to a size of 40 bytes. The client is still desperate to send data as fast as possible, so it generates a 40-byte segment. And so it goes, with likely all the remaining data passing from the client to the server in tiny segments until either the client runs out of data, or the server more quickly clears the buffer.

Now imagine the worst-case scenario. This time, it is the application process on the server that is overloaded. It is drawing data from the buffer one byte at a time. Every time it removes a byte from the server‘s buffer, the server‘s TCP opens the window with a window size of exactly 1 and puts this in theWindow field in an acknowledgment to the client. The client then sends a segment with exactly one byte, refilling the buffer until the application draws off the next byte.

The Cause of Silly Window Syndrome: Inefficient Reductions of Window Size

None of what we have seen above represents a failure per se of the sliding window mechanism. It is working properly to keep the server‘s receive buffer filled and to manage the flow of data. The problem is that the sliding window mechanism is only concerned with managing the buffer—it doesn‘t take into account the inefficiency of the small segments that result when the window size is micromanaged in this way.

In essence, by sending small window size advertisements we are “winning the battles but losing the war”. Early TCP/IP researchers who discovered this phenomenon called it silly window syndrome (SWS), a play on the phrase “sliding window system” that expresses their opinion on how it behaves when it gets into this state.

The examples above show how SWS can be caused by the advertisement of small window sizes by a receiving device. It is also possible for SWS to happen if the sending device isn‘t careful about how it generates segments for transmission, regardless of the state of the receiver‘s buffers.

For example, suppose the client TCP in the example above was receiving data from the sending application in blocks of 10 bytes at a time. However, the sending TCP was so impatient to get the data to the client that it took each 10-byte block and immediately packaged it into a segment, even though the next 10-byte block was coming shortly thereafter. This would result in a needless swarm of inefficient 10-data-byte segments.

Silly Window Syndrome Avoidance Algorithms

Since SWS is caused by the basic sliding window system not paying attention to the result of decisions that create small segments, dealing with SWS is conceptually simple: change the system so that we avoid small window size advertisements, and at the same time, also avoid sending small segments. Since both the sender and recipient of data contribute to SWS, changes are made to the behavior of both to avoid SWS. These changes are collectively termed SWS avoidance algorithms.

Receiver SWS Avoidance

Let‘s start with SWS avoidance by the receiver. As we saw in the initial example above, the receiver contributed to SWS by reducing the size of its receive window to smaller and smaller values due its being busy. This caused the right edge of the sender‘s send window to move by ever-smaller increments, leading to smaller and smaller segments. To avoid SWS, we simply make the rule that the receiver may not update its advertised receive window in such a way that this leaves too little usable window space on the part of the sender. In other words, we restrict the receiver from moving the right edge of the window by too small an amount. The usual minimum that the edge may be moved is either the value of the MSS parameter, or one-half the buffer size, whichever is less.

Let‘s see how we might use this in the example above. When the server receives the initial 360-byte segment from the client and can only process 120 bytes, it does not reduce the window size to 120. It reduces it all the way to 0, closing the window. It sends this back to the client, which will then stop and not send a small segment. Once the server has removed 60 more bytes from the buffer, it will now have 180 bytes free, half the size of the buffer. It now opens the window up to 180 bytes in size and sends the new window size to the client.

It will continue to only advertise either 0 bytes, or 180 or more, not smaller values in between. This seems to slow down the operation of TCP, but it really doesn‘t. Because the server is overloaded, the limiting factor in overall performance of the connection is the rate at which the server can clear the buffer. We are just exchanging many small segments for a few larger ones.

Sender SWS Avoidance and Nagle‘s Algorithm

SWS avoidance by the sender is accomplished generally by imposing “restraint” on the part of the transmitting TCP. Instead of trying to immediately send data as soon as we can, we wait to send until we have a segment of a reasonable size. The specific method for doing this is called Nagle‘s algorithm, named for its inventor, John Smith. (Just kidding, it was John Nagle. J) Simplified, this algorithm works as follows:

  • As long as there is no unacknowledged data outstanding on the connection, as soon as the application wants, data can be immediately sent. For example, in the case of an interactive application like Telnet, a single keystroke can be “pushed” in a segment.
  • While there is unacknowledged data, all subsequent data to be sent is held in the transmit buffer and not transmitted until either all the unacknowledged data is acknowledged, or we have accumulated enough data to send a full-sized (MSS-sized) segment. This applies even if a “push” is requested by the user.

This might seem strange, especially the part about buffering data despite a push request! You might think this would cause applications like Telnet to “break”. In fact, Nagle‘s algorithm is a very clever method that suits the needs of both low-data-rate interactive applications like Telnet and high-bandwidth file transfer applications.

If you are using something like Telnet where the data is arriving very slowly (humans are very slow compared to computers), the initial data (first keystroke) can be pushed right away. The next keystroke has to wait for an acknowledgment, but this will probably come reasonably soon relative to how long it takes to hit the next key. In contrast, more conventional applications that generate data in large amounts will automatically have the data accumulated into larger segments for efficiency.

Nagle’s algorithm is actually far more complex than this description, but this topic is already getting too long. RFC 896 discusses it in (much) more detail.

时间: 2024-10-14 06:42:06

TCP Silly Window Syndrome的相关文章

TCP系列33—窗口管理&流控—7、Silly Window Syndrome(SWS)

一.SWS介绍 前面我们已经通过示例看到如果接收端的应用层一直没有读取数据,那么window size就会慢慢变小最终可能变为0,此时我们假设一种场景,如果应用层读取少量数据(比如十几bytes),接收端TCP有了少量的新的接收缓存后如果立即进行window update把新的window size通告发送端的话,发送端如果立即发送数据,那么接收端缓存可能又会立即耗尽,window size又变为0,接着应用层重复读取少量数据,这个过程重复的话,那么发送端就会频繁的发送大量的小包,这种场景我们就

TCP Sliding Window

Sliding window is an interesting concept. In terms of TCP, receiver's window represents the amount of data that the receiver is willing to accept. In this article, we will cover TCP sliding window concept and aspects related to it. Quick Sender, Slow

关于TCP Zero Window Update感知的非常棒的优化

本文从"然而有一种丢包..."开始步入正题.此前的胡扯可以直接跳过.这个周末是搬入新家的第二个周末,感觉整个人比在罗湖时状态更加好了.也许这个房子的色调跟我上海的家更像吧...不管怎么说,这是我到深圳以后第一个感到振作的地方,以前曾经好几次都想离开了,但是这个家让我决定可以继续坚持.说实话我并不喜欢深圳,虽然我比较喜欢下雨,但是喜欢的是那种持续不断的雨,而不是亚热带雨林式的十分钟暴雨十分钟烈日那种.我喜欢的城市是那种纵深的,30公里回家路可以看完一本书的那种...本来嘛,今天想好好睡一

想深入了解TCP机制和相关参数优化吗(下)

上篇中,我们介绍了TCP的协议头.状态机.数据重传中的东西.但是TCP要解决一个很大的事,那就是要在一个网络根据不同的情况来动态调整自己的发包的速度,小则让自己的连接更稳定,大则让整个网络更稳定.在你阅读下篇之前,你需要做好准备,本篇文章有好些算法和策略,可能会引发你的各种思考,让你的大脑分配很多内存和计算资源,所以,不适合在厕所中阅读. TCP的RTT算法 从前面的TCP的重传机制我们知道Timeout的设置对于重传非常重要, 设长了,重发就慢,没有效率,性能差: 设短了,重发的就快,会增加网

《TCP/IP详解:卷一》-TCP部分讲解

TCP/IP协议 作者:Danbo 2015-7-2 本文为参考TCP/IP详解卷一,某些知识点加上了作者自己的理解,如有错误,欢迎指正,可以微博联系我! TCP包格式和IP包格式如下: TCP的正常建立与关闭 建立连接 TCP协议提供可靠的面向连接服务,采用三次握手建立连接.第一次握手:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认:第二次握手:服务器收到SYN包,向客户端返回ACK(ack=j+1),同时自己也发送一个SYN包(syn=k),

TCP的那些事(转载)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell.cn ,请勿用于任何商业用途) TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是推荐你去看W.Richard Stevens的<TCP/IP 详解 卷1:协议>(当然,你也可以去读一下RFC793以及后面N多的RFC).另外,本文我会使用英文术语,这样方便你通过这些英文关键词来查找相关的技

TCP 的那些事儿(下)

http://coolshell.cn/articles/11609.html 这篇文章是下篇,所以如果你对TCP不熟悉的话,还请你先看看上篇<TCP的那些事儿(上)> 上篇中,我们介绍了TCP的协议头.状态机.数据重传中的东西.但是TCP要解决一个很大的事,那就是要在一个网络根据不同的情况来动态调整自己的发包的速度,小则让自己的连接更稳定,大则让整个网络更稳定.在你阅读下篇之前,你需要做好准备,本篇文章有好些算法和策略,可能会引发你的各种思考,让你的大脑分配很多内存和计算资源,所以,不适合在

TCP小结

TCP/IP协议实现了不同主机,不同操作系统之间信息交流.由4层构成,从上往下依次为: 1.应用层,包括http,ftp等协议,用于实现某一项具体的功能. 2.传输层,包括TCP和UDP,一个可靠,一个快速. 3.网络层,IP协议,完成IP数据包在网络中的传输,但不可靠. 4.数据链路层,主要用于接收和发送IP数据包. 在网络编程中主要接触TCP,UDP协议.这里对TCP的有关知识做一下小结: TCP是面向连接的,可靠的传输协议:通过3次握手建立连接,4次挥手断开连接,通过重传机制实现可靠性,此

关于网络编程中MTU TCP UDP优化设置总结

首先要看TCP/IP协议,涉及到四层:链路层,网络层,传输层,应用层.  其中以太网(Ethernet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据(Data)在应用层 它们的关系是 数据帧{IP包{TCP或UDP包{Data}}} --------------------------------------------------------------------------------- 在应用程序中我们用到的Data的长度最大是多少,直接取决于底层的