【计算机网络】TCP/IP——流量控制与拥塞控制

学习日期:2024.7.22

内容摘要:TCP的流量控制与拥塞控制


流量控制

一般来说,我们总是希望数据传输的快一些,但是如果数据传输的太快,接收方可能就来不及接收,这就会导致数据的丢失,流量控制正是为了避免这一现象。

所谓流量控制,其实就是让发送方的发送速率不要太快,让接收方来得及接收,所以一定是接收方给发送方流量控制。用滑动窗口机制可以很方便的在TCP上实现对发送方的流量控制。

下面我们举一个例子,在这个例子中,为了方便讨论,我们不考虑拥塞控制,而是认为接收窗口与发送窗口大小相等。

如图,一开始流量窗口是400,A向B发送数据,B给A流量控制。图中第三部分,201~300的字节数据丢失了,B就在确认时,ack=201,意思是201号字节之前的数据都收到了,而rwnd=300的意思是,调整接收窗口为300。

 于是,发送窗口被调节为201之后的300个字节,如上图蓝色阴影所示。然后A会从301开始发送(接着上次的)然后发完401~500之后,窗口内的数据已经全部发完,不能再发送新数据了。待重传计时器超时后,A就会开始超时重传旧数据

 如图,当主机A超时重传201~300的数据后,主机b就能对收到的501以前的数据进行累计确认,再把接收窗口调整成为100。主机A的发送窗口会调整为501~600,发完这部分数据后,主机A就不能再发送数据了。此时主机B对601号以前的数据进行了累计确认,ACK=1的意思是确认收到,ack=601的意思是601以前的数据,rwnd=0是接收窗口调整为了0。

因为此时接收窗口是0,所以就不能发送一般的TCP报文了,直到B通知A,接收窗口不为0。

但是这样可能导致一个问题,如果主机B的接收窗口扩大了,它想通知主机A,但这个通告在传输过程中丢失了,这会怎么样呢?

主机A会一直等待主机B告诉它传输窗口已经打开了,而主机B会一直等待主机A发送消息,双方会无限等待下去,这样就会导致死锁。A以为B在忙一直等,B以为自己告诉A了,双方又不交流,就死锁了。

为了解决这个问题,TCP规定,如果收到0窗口通知,发送方就要启动一个持续计时器,每隔一段时间发送一个0窗口探测报文,仅携带1字节数据。就好比A隔一段时间问一下B,“在吗?”,如果B的接收窗口还没调大,就回ACK=1表示收到(确认通信能完成),rwnd=0表示接收窗口为0,就是还在忙。如果可以了,就是rwnd=xxx,这样就能够避免死锁了。


拥塞控制

在某段时间中,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫做拥塞。类比生活中就是堵车,大家都想去一个地方(访问一个处理机),但是路就那么宽,那么就塞车了。

在计算机网络中的链路容量、交换节点中的缓存和处理机等,都叫做“网络的资源”。

若出现拥塞而不进行控制,整个网络的吞吐量将随着输入负荷的增大而下降。

如图,理想的拥塞控制是绿线,在达到阈值前,输入负载始终等于吞吐量,达到之后,吞吐量始终保持最高。这好比公路在达到承载能力上限之前,始终能满负荷运转,而达到之后,即使再多的车来,也能保持以最大限度运转,但塞过车的都知道这是不可能的。

如果无拥塞控制,就是红线,随着车越来越多,大家全部都动不了,最后所有车都堵在路上,吞吐量为0。而实际的拥塞控制,就是要尽量接近理想的拥塞控制。

TCP的拥塞控制主要有慢开始,拥塞避免,快重传,快恢复

为了方便讨论,我们假定:

①数据是单方向传送的,另一个方向只传送确认

②接收方的缓存空间足够大,因而发送方发送窗口的大小以网络的拥塞程度决定,不考虑接收窗口

③以最大报文段MSS的个数为讨论问题的单位,而非字节

慢开始和拥塞避免

传输轮次:发送方给接收方发送后,到接收方给发送方发回对应的确认报文段的时间,其实就是往返时间RTT,这个时间并不是恒定的,会根据具体的网络情况波动。

慢开始算法的过程很简单,一开始拥塞窗口cwnd为1,发送窗口等于拥塞窗口,之后每轮次2,4,8,16这样指数级增大,直到拥塞窗口大于慢开始门限。然后采用拥塞避免算法,其实就是改为每轮次都线性+1,直到发生超时重传(认为此时网络已经开始拥塞),就把慢开始门限值调节为拥塞时的一半,然后从头再来一遍 慢开始—>拥塞避免。

 如图,慢开始门限起初是16,先用慢开始算法,从1开始指数增长到16,然后触发门限值,开始拥塞避免,每次线性+1,直到拥塞窗口为24时,发生了超时重传。此时把门限设置为24的一半,即12,然后从头再慢开始一次,8->16时,改为到门限12,然后从12开始线性增长。

但是这样有个问题,超时重传不一定是网络拥塞,有可能只是报文段在网络中丢失了,这会导致发送方超时重传,并误认为网络发生了拥塞。所以引入了快重传算法。

快重传

所谓“快重传”,就是要发送方尽快进行重传,而不是等到超时重传计时器超时再重传

①要求接收方不要等到字节要发送数据时顺带确认,而要立刻发送确认

②即使收到了失序的报文段,也要对已收到报文段发出重复确认

③发送方一旦收到3个连续的重复确认,就立刻重传相应的报文段,而不是等待超时重传计时器超时

如图,我们还是把发送方和接收方分别命名为A和B

A发送M1,B收到后立刻确认M1,A在收到M1确认前就发送M2,B确认M2,A发送M3,但是此时M3丢失,B不知道,自然不会确认。

于是A发送M4,B发现这不是按顺序到达的报文,于是重复确认自己收到的最晚的一条信息M2,A继续发送M5,B发现这不是按顺序到达的报文,重复确认M2,A发送M6后同理,此时A连续收到了三次对M2的确认,于是A重复发送M3,无需等待M3的超时重传计时器

B在收到M3后,已经有了M1到M6的报文,所以B确认M6,A就知道B已经收到了M1到M6的报文。

快恢复

快恢复和快重传搭配使用,发送方一旦收到了3个重复确认,就知道现在只是丢失了个别的报文段,于是不使用慢开始算法,而是用快恢复算法,其实就是慢开始算法跳过了“慢开始”部分,而是直接把慢开始门限值和拥塞窗口调整为当前窗口的一半,然后开始执行拥塞避免算法。

说人话就是,拥塞窗口直接减半,然后依旧每次+1线性增长

如图,第一次慢开始到达门限16,然后线性增长到24,发生超时重传,门限改为12,慢开始到12,然后线性增长到16,然后发生快重传,快恢复到8,继续线性增长。


感谢您看到这里,如果满意的话麻烦您点个赞支持一下,主页还有更多内容分享。

内容总结自bilibili用户 湖科大教书匠的《计算机网络微课堂》和中国工信出版集团《图解TCP/IP》

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 21:48:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 21:48:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 21:48:02       45 阅读
  4. Python语言-面向对象

    2024-07-22 21:48:02       55 阅读

热门阅读

  1. 多站点环境下Memcached的配置与管理

    2024-07-22 21:48:02       18 阅读
  2. Vue3 深入组件

    2024-07-22 21:48:02       17 阅读
  3. Leetcode热题100 Day4

    2024-07-22 21:48:02       16 阅读
  4. Python每日学习

    2024-07-22 21:48:02       15 阅读
  5. web前端 React 框架面试200题(七)

    2024-07-22 21:48:02       15 阅读
  6. 鸡兔同笼求解器

    2024-07-22 21:48:02       17 阅读
  7. 深度学习中的损失函数和网络优化方法

    2024-07-22 21:48:02       13 阅读
  8. VUE复习

    VUE复习

    2024-07-22 21:48:02      10 阅读
  9. Unity扩展 UI线段绘制组件——UI上的LineRenderer

    2024-07-22 21:48:02       14 阅读