之前说过,拥塞控制是全局的问题,是由网络中所有主机,路由器共同完成的,而流量控制只涉及到端端之间的传输,是局部问题。TCP的拥塞控制是通过调节拥塞窗口的大小来进行的,拥塞窗口(CongWin)体现出来了网络的承受能力。发送端的有效窗口必须兼顾网络和接收能力:SendWin = min(接收窗口,拥塞窗口),发送端必须凭借此公式调整发送速率以避免网络拥塞造成的丢包。如下图的示意图,网络中限制传输速率一定是由最小的那一环决定的,而这一环往往取决于内部的拥塞,所以用拥塞窗口来调节发送速率是一个非常好的选择。
那么回到拥塞控制本身。拥塞控制有几个问题需要解决:第一,如何知晓自己的线路发生了拥塞?第二,发生了拥塞,用什么算法进行处理?TCP拥塞控制为这两个问题给出了自己的答案。
第一,怎么判定网络的拥塞?①段的计时器超时了。当发生拥塞时,发送端和接收端之间路径上一个或者多个路由器的缓冲区溢出,导致数据报被丢弃。这会导致发送方长时间收不到反馈从而导致超时; ②收到三个重复的ACK(快速重传机制) 简单来说,就是某一个包丢了,但是它之后的包都正常达到,那么接受方发现只有某一个包丢了,就向源端连续发送三个ACK,ACK带有期待的包的序号,发送端收到这三个连续ACK,便不等到段计时器超时,直接发送对应的序号的数据包,这就是快速重传机制。这两个方法,能让发送方掌握网络发生了拥塞,进而采用算法来调整自己的发送速率。
第二,采用什么算法。我们假设接收缓冲区足够大,那么对于 min(接收窗口,拥塞窗口),实际中起到影响作用的只有拥塞窗口CongWin. 设 RTT 为TCP段开始发送到ACK返回的时间,也就是一个数据包发送所需要的时间,那么发送端的发送速率近似为CongWin/RTT bps。 所以TCP发送端通过调整CongWin来限制发送速率。
速率调整算法的基本思想是:当发生丢包事件时,降低发送速率(减少拥塞窗口CongWin的大小)。 所有通过壅塞区域的发送端都降低发送速率注入拥塞路径的流量减少,由此缓解壅塞状况。算法主要由三个部分组成: 慢启动,逐步递增加倍递减(AIMD),响应超时。
1.慢启动 (1)TCP连接建立时,拥塞窗口CongWin初始为一个MSS(MSS是最大段长度,是能通过网络的最大段的长度),所以初始发送速率为CongWin/RTT。
(2)每经过一个RTT,CongWin的大小加倍(以MSS为单位)。在初始阶段,按指数增长速度加大发送速率直到发生“丢包事件”。
(3)发生“丢包事件”后,将CongWin窗口减半,之后就按照按线性速度增大(每个RTT增大一个MSS).
慢启动的示意图如上所示
2.AI(Additive-Increase)MD(Multiplicative Decrease)逐步递增加倍递减算法 这是拥塞避免阶段的算法,采用这个算法的时候已经出现了第一次丢包,丢包后就离开了慢启动部分,开启了AIMD算法。
逐步递增:每当经过一个RTT就将CongWin窗口增大一个MSS。
加倍递减:一旦发现丢失段立即将CongWin窗口减半(最后减到1),对于保留在发送窗口中的段将重传计时器的值加倍。
计时器加倍这件事情很有意义,因为如果不这么做,那么由于已经拥堵,那么大概率下之后的包按照原来的计时器计时很有可能还会超时,所以加倍之后避免超时的发生。所以拥塞窗口的变化成左斜边的锯齿状:
3. 响应超时(丢包事件) 对于不同种类的超时,算法的响应是不一样的。超时有两种:①某个段超时 ②三个连续ACK。 这两种超时的意义不同,前者代表不确定后面也丢了还是没丢,但是第二种快速重传代表以后的还存在,只是这个包丢了。前者的网络拥塞程度比后者大,所以算法采用不同的响应。
(1)某个段超时:发送端进入“慢速启动”阶段,拥塞发送窗口直接置为1个MSS;按指数增长直到CongWin= 发生超时时的一半;按线性增长(进入拥塞避免阶段)。
(2)三个重复ACK:拥塞窗口减半;按线性增长。
某个段超时之后直接就会给它的拥塞发送窗口设置为1个MSS,之后就按照之前说的步骤,重头再来,只不过拥塞窗口CongWin变成原来的一半了。而ACK快速重传机制只是把CongWin设为原来的一般,按照线性增长,它省去了慢启动的步骤。示例图如下:
我们来看,段超时的是③曲线对应的,他有着完整地慢启动,逐步递增加倍递减的过程,但是如果只是快速重传④,那么只是拥塞窗口减半,在这个基础上进行逐步递增就可以了,它没有慢启动(指数增长)的过程。
上面就是TCP拥塞控制的完整介绍。
拓展阅读