# 网络基本功(十一):TCP窗口调整与流控
**转载请在文首保留原文出处:EMC中文支持论坛**[https://community.emc.com/go/chinese](https://community.emc.com/go/chinese) [![image001.gif](https://community.emc.com/servlet/JiveServlet/downloadImage/2-843667-97586/image001.gif)](http://service.weibo.com/share/share.php?title=%23ECN%e4%b8%ad%e6%96%87%e6%94%af%e6%8c%81%e8%ae%ba%e5%9d%9b%23 %e7%bd%91%e7%bb%9c%e5%9f%ba%e6%9c%ac%e5%8a%9f%ef%bc%88%e5%8d%81%e4%b8%80%ef%bc%89%ef%bc%9aTCP%e7%aa%97%e5%8f%a3%e8%b0%83%e6%95%b4%e4%b8%8e%e6%b5%81%e6%8e%a7 @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)
## 介绍
前文已经介绍过了TCP滑动窗口大小的重要性。在客户端与服务器的连接中,客户端告知服务器它一次希望从服务器接收多少字节数据,这是客户端的接收窗口,即服务器的发送窗口。类似地,服务器告知客户端一次希望从客户端接收多少字节数据,也就是服务器的接收窗口和客户端的发送窗口。
要理解为什么窗口大小会产生波动,首先需要理解它的含义。最简单的方式是它代表了设备对于特定连接的接收缓存大小。即,窗口大小代表一个设备一次能够从对端处理多少数据,之后再传递给应用层处理。
## 更多信息
当服务器从客户端接收数据,它就将数据放在缓存中,服务器必须对数据做以下两步操作:
**确认**:服务器必须将确认信息发回客户端以表明数据接收。
**传输**:服务器必须处理数据,将它传递给目标应用程序处理。
区分开这两件事情是非常重要的。关键在于基本的滑动窗口机制中,数据于接收时确认,但并不一定立即从缓存中传输出去。也就意味着当接收数据速度快于接收TCP处理速度时,缓存有可能被填满。当这一情况发生时,接收设备需要调整窗口大小已防止缓存过载。
由于窗口大小能够以这种方式管理连接两端设备数据流的速率,TCP就是以这种方式实现流控这一传输层非常典型的任务。流控对于TCP来说是很重要的,因为它是设备间互通状态的方式。通过增加或缩小窗口大小,服务器和客户端能够确保对端发送数据的速度等同于处理速度。
**减小窗口大小以降低发送速率:**
首先看一下客户端到服务器的数据传输,如下图所示。
[![image002.jpg](https://community.emc.com/servlet/JiveServlet/downloadImage/2-843667-97608/image002.jpg)](https://community.emc.com/servlet/JiveServlet/showImage/2-843667-97608/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](https://community.emc.com/servlet/JiveServlet/downloadImage/2-843667-97609/image003.jpg)](https://community.emc.com/servlet/JiveServlet/showImage/2-843667-97609/image003.jpg)
**缩减发送窗口以停止发送新数据:**
如果服务器无法接收任何新数据会怎么样呢?假设客户端下一次传输180字节,但是服务器太忙碌而无法对其进行处理。这种情况下,服务器将这180字节缓存下来,并且在确认信息中,将窗口大小从260字节缩减为80字节。当客户端接收到180字节的确认信息,它也会看到窗口缩减了180字节,它会滑动与缩减同样的大小,告知服务器:我确认接收180字节数据,但不允许你再发送新的数据。也可以看作窗口左端滑动180字节,但右端维持不动。只要右端不移动,客户端就无法发送更多数据。这一过程显示在上图的4-6中。
**关闭发送窗口:**
窗口调整可以通过双方设备来完成。如果服务器从客户端接收的数据持续快于推送给应用的速率,则服务器将会继续减小接收窗口。假设发送窗口减小至80字节,客户端发送第三个请求,长度为80字节,但服务器仍处于繁忙状态。之后服务器将窗口减小为0,也称为关闭窗口。这一信息告知客户端服务器已经过载,它需要彻底停止发送数据,如上图最后一步所示。之后,当服务器负载减轻时,可以再次增加这一连接的窗口,允许更多数据传输。
- 介绍
- 网络基本功(一):细说网络传输
- 网络基本功(二):细说交换机
- 网络基本功(三):细说VLAN与Trunk
- 网络基本功(四):细说路由(上)
- 网络基本功(五):细说路由(下)
- 网络基本功(六):链路聚合
- 网络基本功(七):细说IP地址与子网
- 网络基本功(八):细说TCP滑动窗口
- 网络基本功(九):细说TCP重传
- 网络基本功(十):细说TCP确认机制
- 网络基本功(十一):TCP窗口调整与流控
- 网络基本功(十二):细说Linux网络配置(上)
- 网络基本功(十三):细说Linux网络配置(下)
- 网络基本功(十四):细说诊断工具ping
- 网络基本功(十五):细说网络性能监测与实例(上)
- 网络基本功(十六):细说网络性能监测与实例(下)
- 网络基本功(十七):细说tcpdump的妙用(上)
- 网络基本功(十八):细说tcpdump的妙用(下)
- 网络基本功(十九):细说NAT原理与配置
- 网络基本功(二十):细说ICMP和ARP
- 网络基本功(二十一):细说HTTP(上)
- 网络基本功(二十二):细说HTTP(下)
- 网络基本功(二十三):Wireshark抓包实例诊断TCP连接问题
- 网络基本功(二十四):Wireshark抓包实例分析TCP重传
- 网络基本功(二十五):Wireshark抓包实例分析TCP重复ACK与乱序
- 网络基本功(二十六):Wireshark抓包实例分析TCP窗口及reset
- 网络基本功(二十七):Wireshark抓包实例分析HTTP问题(上)
- 网络基本功(二十八):Wireshark抓包实例分析HTTP问题(下)
- 网络基本功(二十九):Wireshark抓包实例诊断数据库常见问题
- 网络基本功(三十):细说DNS(上)
- 网络基本功(三十一):细说DHCP