TCP的流量控制与拥塞控制

流量控制(滑动窗口)

TCP通过滑动窗口机制防止接收方处理数据的速度跟不上发送方,避免随着时间推移,数据自然溢出接收方的缓冲区。

发送端

发送方会建立自己的滑动窗口,按三个标准划分:是否发送、是否收到ACK、是否在接收方通告处理范围内。

  1. 已经发送并且收到ACK的部分,已经成功发送,不需要在缓冲区保留;
  2. 已经发送但未收到ACK
  3. 可用窗口:还没有发送,但是还在接收方窗口处理范围内(第二、三部分为整个发送窗口);

可用窗口大小=SND.WND+SND.UNA-SND.NXT

  • SND.WND:发送窗口,32-51

  • SND.UNA:指针,指向已发送未确认的字节,如上图SND.UNA=32

  • SND.NXT:可用窗口的第一个字节,如上图SND.NXT=46

  1. 需要发送,但是超过接收方窗口范围的部分。在没有收到新的ACK之前,发送方不会发送这些数据,通过这个限制,发送的数据就不会超过接收方缓冲区;

如果ACK在网络传输中丢包,发送端就不会感知到接收端窗口的变化,发送方一直没有收到ACK,随着数据不断发送,可用窗口会被占满,发送方认为接收端处于零窗口状态,就不会继续发送数据,接收端也一直在等待发送端发送数据,进入了死锁状态。

解决办法:引入零窗口计时器,如果发送端陷入零窗口状态,就启动计时器,定时询问接收端窗口是否可用。

随着ACK或进程读取数据,窗口会顺次后移。如果接收到ACK,表示之前的数据都收到了,那么可用窗口就会顺次右移

接收端

接收端的窗口分为已经接收并确认的区域、未收到但是可以接收的区域(接收窗口),剩下的是不可接收的区域。

如果进程读取缓冲区的速度有变化,接受端就会相应调整接收窗口的大小,并告诉发送端,就可以控制发送端的发送速度

拥塞控制

在实际网络中,由于大量的包传输,可能导致中间某些节点的缓冲区满载,多余的包被丢弃,需要重新发送,最差的情况,网络上的包都是重传的包并且被反复丢弃,整个网络的传输能力降为0.

TCP协议使用拥塞窗口机制解决这个问题。当节点发现自己的部分包丢的时候,有理由怀疑网络发生了拥塞,大部分节点会减少自己传输的包,这样网络拥塞环境就会得到缓解。在发送端定义一个窗口CWND(congestion window)发送端最大的发送范围是拥塞窗口和滑动窗口中较小的一个。

拥塞窗口的大小动态地随着网络情况调整,拥塞控制算法主要包括四个部分:

  • 慢启动:在不确定拥塞是否会发生的情况下,会采用倍增的方式逐渐增加窗口的大小;
  • 拥塞避免:在窗口增加到一定程度时,减缓增加的速度,转为线性扩大窗口的方式(每次收到ACK没有丢包的情况下只比上次窗口增大1);
  • 拥塞发生:当网络遇到丢包的情况,一方面进行超时重传快速重传,另一方面缩小窗口的范围;
  • 快速恢复
    • 快速重传:如果连续3次收到重复的ACK,说明部分丢包,这时采用快速恢复(拥塞窗口变为原来的一半,ssthresh设置成当前窗口大小,再执行拥塞避免算法。有时会设置CWND=ssthresh+3);
    • 超时重传:拥塞比较严重,直接将ssthresh设置为原来的一半,窗口重置为1,再进入慢启动阶段;

两者区别(参考AI生成结果)

流量控制主要是控制发送方发送数据的速率,以避免接收方来不及处理接收到的数据,造成数据的丢失。流量控制是一种端到端的控制机制,它确保发送方的发送速率与接收方的处理能力相匹配。在TCP协议中,流量控制是通过滑动窗口机制实现的,接收方通过返回的ACK中包含的窗口大小来告诉发送方自己的接收能力(基于反馈进行控制)。

拥塞控制则是防止过多的数据注入到网络中,从而使网络中的路由器或链路不会过载。拥塞控制是一种全局性的控制机制,它关注的是整个网络的运行状态,而不仅仅是两个端点之间的通信。TCP协议中的拥塞控制是通过慢启动、拥塞避免、快速重传和快速恢复等算法来实现的,这些算法根据网络的拥塞程度来调整数据传输的速率。

总结:流量控制是为了让发送方的发送速率与接收方的处理能力相匹配,是局部性过程的而拥塞控制是为了让整个网络的数据传输量处于网络可以处理的范围内,是全局性过程

数据链路层的流量控制是点对点的,数据链路层流量控制的手段是接收方收不下就不回复确认帧。传输层的流量控制手段是接收端通过滑动窗口告诉发送方。

参考资料

  1. 滑动窗口:TCP是如何进行流量控制和拥塞控制的?
  2. TCP Sliding Window Data Transfer and Acknowledgement Mechanics
  3. 传输层&数据链路层流量控制