网络基本功(十一):TCP窗口调整与流控

转载请在文首保留原文出处:EMC中文支持论坛https://community.emc.com/go/chinese
@EMC%e6%98%93%e5%ae%89%e4%bf%a1%e4%b8%ad%e5%9b%bd%e6%8a%80%e6%9c%af%e7%a4%be%e5%8c%ba&url=https://community.emc.com/message/843667#843667">image001.gif

介绍

前文已经介绍过了TCP滑动窗口大小的重要性。在客户端与服务器的连接中,客户端告知服务器它一次希望从服务器接收多少字节数据,这是客户端的接收窗口,即服务器的发送窗口。类似地,服务器告知客户端一次希望从客户端接收多少字节数据,也就是服务器的接收窗口和客户端的发送窗口。

要理解为什么窗口大小会产生波动,首先需要理解它的含义。最简单的方式是它代表了设备对于特定连接的接收缓存大小。即,窗口大小代表一个设备一次能够从对端处理多少数据,之后再传递给应用层处理。

更多信息

当服务器从客户端接收数据,它就将数据放在缓存中,服务器必须对数据做以下两步操作:

确认:服务器必须将确认信息发回客户端以表明数据接收。

传输:服务器必须处理数据,将它传递给目标应用程序处理。

区分开这两件事情是非常重要的。关键在于基本的滑动窗口机制中,数据于接收时确认,但并不一定立即从缓存中传输出去。也就意味着当接收数据速度快于接收TCP处理速度时,缓存有可能被填满。当这一情况发生时,接收设备需要调整窗口大小已防止缓存过载。

由于窗口大小能够以这种方式管理连接两端设备数据流的速率,TCP就是以这种方式实现流控这一传输层非常典型的任务。流控对于TCP来说是很重要的,因为它是设备间互通状态的方式。通过增加或缩小窗口大小,服务器和客户端能够确保对端发送数据的速度等同于处理速度。

减小窗口大小以降低发送速率:

首先看一下客户端到服务器的数据传输,如下图所示。

image002.jpg

客户端传输140字节数据至服务器。之后,客户端的可用窗口还剩下220字节:发送窗口的360字节减去发送的140字节。

一段时间过后,服务器接收到140字节并将它们放在缓存中。现在,理想的情况下,140字节进入缓存,确认之后立刻从缓存移出。也就是说,缓存有足够的大小来容纳客户端发送的所有数据。缓存的空闲空间维持在360字节,因此告知客户端窗口大小保持不变。

只要服务器处理速度和数据进入速度相同,窗口大小就会保持在360字节。客户端在接收到140字节的确认信息以及窗口大小保持不变的信息之后,将360字节窗口向右移动140字节。由于现在未确认字节数为0,因此客户端又可以发送360字节数据。对应于之前可用窗口的220字节,加上刚刚确认的140字节数据。

然而,现实中服务器可能需要处理数十,数百乃至数千个TCP连接。TCP可能无法立刻处理数据,或应用应用程序本身无法接收140字节数据。任何一种情况下,服务器TCP都无法立刻将140字节从缓存中移出。这时,除了发回确认信息给客户端以外,服务器会想要告知客户端更改窗口大小,以表示缓存已经被部分写入了。

假设我们接收到140字节,但只能发送40字节给应用程序,缓存中剩下100字节。当发送140字节的确认信息,服务器将发送窗口缩小100字节,至260字节。当客户端从服务器接收到这一片段,它将会看到140字节的确认信息并将窗口向右滑动140字节。在滑动过程中,将大小缩减至260字节。可以认为将窗口左端滑动140字节,但右端仅滑动40字节。新的稍小一些的窗口保证服务器从客户端接收最多260字节数据,以适应接收缓存中的剩余空间,如下图的1-3步所示。

image003.jpg

缩减发送窗口以停止发送新数据:

如果服务器无法接收任何新数据会怎么样呢?假设客户端下一次传输180字节,但是服务器太忙碌而无法对其进行处理。这种情况下,服务器将这180字节缓存下来,并且在确认信息中,将窗口大小从260字节缩减为80字节。当客户端接收到180字节的确认信息,它也会看到窗口缩减了180字节,它会滑动与缩减同样的大小,告知服务器:我确认接收180字节数据,但不允许你再发送新的数据。也可以看作窗口左端滑动180字节,但右端维持不动。只要右端不移动,客户端就无法发送更多数据。这一过程显示在上图的4-6中。

关闭发送窗口:

窗口调整可以通过双方设备来完成。如果服务器从客户端接收的数据持续快于推送给应用的速率,则服务器将会继续减小接收窗口。假设发送窗口减小至80字节,客户端发送第三个请求,长度为80字节,但服务器仍处于繁忙状态。之后服务器将窗口减小为0,也称为关闭窗口。这一信息告知客户端服务器已经过载,它需要彻底停止发送数据,如上图最后一步所示。之后,当服务器负载减轻时,可以再次增加这一连接的窗口,允许更多数据传输。

原文: https://wizardforcel.gitbooks.io/network-basic/content/10.html