【Linux】TCP的拥塞控制

时间:2024-04-13 08:08:11

拥塞控制原理

拥塞: 在某段时间,若对网络中资源(带宽、交换节点缓存,处理机)的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这种现象就称为拥塞。

拥塞的危害
若网络中的许多资源同时产生拥塞,网络的性能就明显会变坏,整个网络的吞吐量将下降的严重。

出现拥塞的原因:对资源的需求和 大于 可用资源

增加资源能解决拥塞吗
不能。网络拥塞是一个非常复杂的问题,很多情况下,不能解决网络拥塞问题。

网络拥塞往往是由许多因素引起的,例如:

  1. 增大缓存,但是却未提高输出链路的容量和处理机的速度,排队等待的时间将会大大的增加,引起大量超时重传,解决不了网络拥塞。
  2. 提高处理机处理的速率,会将瓶颈转移到其他地方,解决不了网络拥塞
  3. 若一个路由器没有足够的缓存空间,则就会丢弃一些新的分组,但是分组被丢弃之后,发送分组的发送端会继续重传该分组,可能重传多次。这样会引起更多的分组流入网络被网络中的路由器丢弃。可见,拥塞引起的重传反而会加剧网络拥塞

TCP拥塞控制的方法

TCP采用基于窗口的方法进行拥塞控制。TCP发送维持一个拥塞窗口CWND

  1. 拥塞窗口大大小取决于网络拥塞程度,并且动态的变化
  2. 发送端利用拥塞窗口根据网络的拥塞情况调整发送的数据量
  3. 所以,发送窗口的大小不仅仅取决于接收方公告的接收窗口,还取决于网络的拥塞状况,所以真正的发送窗口的窗口值为:
    真正的发送窗口值 = min(公告窗口值,拥塞窗口值)

拥塞窗口的原则

  1. 只要网络没有出现拥塞,拥塞窗口就可以再大一些,以便把更多分组发送出去,这样可以提高网络的利用率
  2. 但是只要网络罗出现拥塞,就必须把拥塞窗口减小一些,以减少注入到网络中的分组数,以便缓解网络出现的拥塞

两种拥塞的方式

  1. 重传定时器超时 —启用拥塞避免算法
    通信的线路一般质量都很好,因传输出差错而丢弃分组的概率很小的。只要是出现了超时,就说明网络中出现了拥塞。
  2. 收到三个相同的ACK回复 – 启用快重传算法与快恢复算法
    个别报文端在网络中丢失,预示着可能会出现拥塞,因此可以尽快采取控制措施,避免拥塞

TCP拥塞控制算法

  1. 慢开始
  2. 拥塞避免
  3. 快重传
  4. 快恢复

慢开始

算法思路:有小到大逐渐增大拥塞窗口的数值。
初始的拥塞窗口cwnd设置: 初始的cwnd窗口大小设置为1到2个发送方最大报文段(MSS)的大小
并且引入了一个新概念:
慢开始门限ssthresh(状态变量):防止拥塞窗口cwnd增长过大引起网络阻塞。到达慢开始门限就开始拥塞控制。

传输轮次的概念

  • 使用慢开始算法后,没经过一个传输轮次,拥塞窗口cwnd就加倍
  • 一个传输轮次所经历的时间就是往返时间RTT(报文的最大生命周期)
    例如:拥塞窗口cwnd = 4, 这是往返时间RTT就是发送方连续发送4个报文段,并收到这4个报文段的确认,总共经历的时间。

慢开始算法中cwnd随着传输轮次而加倍的过程:
【Linux】TCP的拥塞控制

设置慢开始门限状态变量ssthresh
慢开始门限ssthresh的用法如下:

  1. 当cwnd < ssthresh时,使用慢开始算法
  2. 当cwnd > ssthresh时,停止使用慢开始算法而改用拥塞避免算法
  3. 当cwnd == ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法。

拥塞避免算法

算法思路
让拥塞窗口cwnd缓慢增大,即每经过一个往返时间RTT就把发送方的阻塞窗口cwnd +1, 使拥塞窗口cwnd按线性规律缓慢增长

注意:拥塞避免 并非能够完全避免了拥塞,而是说在拥塞避免阶段是按照线性规律增长的,使网络比较不容易出现拥塞。

当网络出现拥塞时(针对于重传定时器超时的拥塞):
无论是在慢开始阶段还是在拥塞避免阶段,只要网络出现拥塞(重传定时器超时):

  1. ssthresh = max(cwnd/2,2)
  2. cwnd = 1
  3. 执行慢开始算法
    目的:迅速减少主机发送到网络中的分组数,使得发送拥塞的路由器有足够时间把队列中的分组处理完毕。

快重传算法

采用快重传FR算法可以让发送方尽早知道发生了个别报文段的丢失
快重传算法:首先要求接收方不要等待自己发送数据时才进行稍待确认,而是要立即发送确认,即使收到了失序的报文段也要立即发出对已收到报文段的重复确认。

发送发只要一连收到三个重复确认,就知道接收方确实没有收到报文段,因而应当立即进行快重传,这样就不会出现超时,发送方也不会误认为出现了网路拥塞。提高网络的吞吐量。

快重传的示意图:
【Linux】TCP的拥塞控制

快恢复算法:

当发送端收到连续三个重复的ACK确认时,由于发送方现在认为网络很有可能没有阻塞,因此现在不执行慢开始算法,而是执行快恢复算法

  1. 慢开始门限ssthresh = 当前拥塞窗口 = cwnd/2
  2. 新拥塞窗口cwnd = 慢开始门限ssthresh
  3. 开始执行拥塞避免算法,使拥塞窗口缓慢的线性增大。

四种算法的实现举例

【Linux】TCP的拥塞控制

规定:发送端的发送窗口不能超过拥塞窗口cwnd和接收端窗口rwnd中的最小值。我们假定接收端窗口足够大,因此现在发送窗口的数值等于拥塞窗口的数值。

  1. 当TCP连接进行初始化时,将拥塞窗口置为1。图中的窗口单位使用的是报文段。 慢开始门限的初始值设置为16个报文段,即ssthresh = 16
  2. 在执行慢开始算法时,拥塞窗口cwnd = 1,发送第一个报文段。发送方没收到一个对新报文段的确认ACK,就把拥塞窗口的值翻倍,然后开始下一轮的传输。因此拥塞窗口cwnd随着传输轮次按指数规律增长
  3. 当拥塞窗口cwnd增长到慢开始门限值ssthresh时(图中的点1,此时的拥塞窗口cwnd=16),就改为执行阻塞避免算法,拥塞窗口按规律线性增长
  4. 当拥塞窗口cwnd = 24时,网络中出现了超时(图中2),发送方判断为网络拥塞。于是调整门限值, ssthresh = cwnd / 2 = 12,同时设置拥塞窗口cwnd = 1, 进入慢开始阶段
  5. 按照慢开始算法,发送方每收到一个对新报文段的确认ACK,就把拥塞窗口值加1。当拥塞窗口swnd = ssthresh = 12时(图中3),改为拥塞避免算法,继续按线性规律增大
  6. 当拥塞窗口cwnd = 16时,出现了一个新的情况,就是发送发一连收到3个对同一报文段的ACK重复确认(图中4),发送发改为执行快速重传和快恢复算法。
  7. (图中4)发送方直到现在只是丢失了个别的报文段。于是不启动慢开始,而是执行快恢复算法。发送方调整门限ssthresh = cwnd/ 2 = 8,同时设置拥塞窗口 cwnd = ssthresh = 8(图中的5),并开始执行拥塞避免算法

总结

在拥塞避免阶段,拥塞窗口是按照线性规律增大的,通常称为"加法增大"。(AI)
当出现超时或3个重复的确认时,就要把门限值设置为当前拥塞窗口值的一半,并大大减小拥塞窗口的数值。 这通常称为"乘法减小" (MD)
二者合在一起就是所谓的 AIMD算法

TCP阻塞控制流程图
【Linux】TCP的拥塞控制