计算机网络 理解拥塞控制

news/2024/5/18 14:09:39 标签: tcp/ip, udp, http
http://www.w3.org/2000/svg" style="display: none;">

文章目录

  • 前言
  • 如何检测拥塞
  • 拥塞控制方法分类
  • 通过窗口减缓TCP发送
  • 拥塞控制算法
    • 理论基础
    • 状态迁移图
    • 慢启动
    • 拥塞避免
    • 快速恢复
    • 总结

前言

TCP的流量控制服务完成了对发送方发送速率的调节——当TCP通信的接收方的接收速率无法匹配发送速率时,发送方会降低发送速率。但流量控制没有考虑到整个网络中的情况——即使路由器能够存储一些数据,但若源源不断的数据到达速率高于路由器的发出速率,任何容量的路由器都会溢出。

路由器因无法处理高速率到达的流量而被迫丢弃数据的现象被称为——拥塞

从流量控制服务可知,针对于丢包情况,TCP采取的首要机制是重传,包括超时重传快速重传。但如果网络已经处于了拥塞状态,你再进行重传,会导致同一时间段内网络传输路径上需要传输更多的数据包。这就好比火上浇油,拥塞的情况会更加严重。

所以,拥塞控制的原则为:

  • 当拥塞状况出现时,我们就需要减缓TCP发送端的发送速率。
  • 当拥塞状况好转时,我们就需要检测和使用新的可用带宽。

如何检测拥塞

但是检测拥塞却很难做到,因为对于TCP的发送方来说,没有一个精确的方法去知晓中间路由器的状态。换言之,没有一个明确的信号告知拥塞状况已经发生。

往深了说,网络层没有为运输层拥塞控制提供显示支持。即使网络中存在拥塞,端系统也必须通过对网络行为的观察(如分组丢失与时延)来推断。

有两种行为可以观察

  • 期待的ACK超时未到达。
  • 收到了三个冗余ACK。

拥塞控制方法分类

  • 端到端拥塞控制。端系统通过观察丢包行为(通过超时或3次冗余ACK而得知)。
  • 网络辅助的拥塞控制。网络层构件(即路由器)向发送方提供关于网络中拥塞状态的显式反馈信息,一般来说我们不能依靠这种方式。分为两种:
    • 路由器直接反馈信息给发送方。
    • 路由器标记或更新从发送方流向接收方的分组中的某个字段来表示拥塞的发生。接收方收到这个分组后,再向发送方通知网络拥塞。这种形式更慢,需要一个完整的往返时间。

通过窗口减缓TCP发送

在流量控制服务中,用接受窗口 r w n d rwnd rwnd来限制发送方可以发送的数据量。在拥塞控制中,我们用拥塞窗口 c w n d cwnd cwnd(congestion window)来限制。那么发送方实际可用窗口 W W W为二者的较小者:
W = m i n { c w n d , r w n d } W = min\{ cwnd, rwnd\} W=min{cwnd,rwnd}

为了仅关注于拥塞控制,本文假设TCP接受缓存无限大,即 r w n d rwnd rwnd无限大。那么 W = c w n d W = cwnd W=cwnd
https://img-blog.csdnimg.cn/4c825239ed3c4f2cb0c2ad4fc442a7a8.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBAYW5saWFuNTIz,size_40,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述" />
且已发送、待确认的数据量不会超过 W W W
L a s t B y t e S e n t − L a s t B y t e A c k ≤ W LastByteSent - LastByteAck \leq W LastByteSentLastByteAckW

已发送、待确认的数据量有时也被称为在外数据量(flight size)。

拥塞控制算法

主要包含这三部分:

  1. 慢启动
  2. 拥塞避免
  3. 快速恢复

慢启动和拥塞避免是TCP的强制部分,二者的差异在于:对收到的ACK做出反应时增加 c w n d cwnd cwnd长度的方式。
快速恢复是推荐部分,不是必需的。

理论基础

慢启动和拥塞避免是基于包守恒ACK时钟原理的。
https://img-blog.csdnimg.cn/7eb7ada7a8204ab2942f4cac038d2de7.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBAYW5saWFuNTIz,size_46,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述" />
守恒指的是——某个量进入一个系统不会凭空消失或出现,而是以某种表现形式继续存在。在上图中,上面的数据包在被接收方接收后就会变成下面的ACK包。

在高效传输的稳定状态下,上下通道都不会出现包堵塞的情况,而且在上通道中也不会有较大传输间隔。注意到,每当发送包接收到一个ACK,就代表其可以向上层通道发送一个数据包。这种由一个ACK到达(称为ACK时钟)触发一个新数据包传输的关系称为自同步(self-clocking)。

状态迁移图

https://img-blog.csdnimg.cn/f9620053bf7a4f429744f4f4655d1884.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBAYW5saWFuNTIz,size_39,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述" />

s s t h r e s h ssthresh ssthresh为slow start threshold即慢启动阈值。

  • c w n d < s s t h r e s h cwnd < ssthresh cwnd<ssthresh时,使用慢启动算法。
  • c w n d > s s t h r e s h cwnd > ssthresh cwnd>ssthresh时,使用拥塞避免算法。
  • c w n d = s s t h r e s h cwnd = ssthresh cwnd=ssthresh时,任何一种算法都可以。

有两种ACK:

  • new ACK,指发送方收到的ACK包里的Ack序号是大于 L a s t B y t e A c k LastByteAck LastByteAck的。
  • duplicate ACK,指发送方收到的ACK包里的Ack序号是等于 L a s t B y t e A c k LastByteAck LastByteAck的。

慢启动

当一个新的TCP连接建立、或检测到 由超时引起的重传 时,需要执行慢启动。TCP发送端长时间处于空闲状态也可能调用慢启动算法。慢启动的目的是,使TCP在使用拥塞避免算法之前就找到一个 c w n d cwnd cwnd值,以及帮助TCP建立ACK时钟。

开始时, c w n d cwnd cwnd的值通常设置为一个MSS的较小值,这使得初始发送速率大约为 M S S R T T \frac{MSS}{RTT} RTTMSS
https://img-blog.csdnimg.cn/2a48d6b647154cda9b8f6eec72add791.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBAYW5saWFuNTIz,size_36,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述" />
该算法的过程为:发送方每收到一个ACK, c w n d cwnd cwnd就增加一个MSS。这样,发送方每经过一个RTT的时间, c w n d cwnd cwnd就会翻倍。从上面的折线图,可以看到窗口大小呈指数形增长(只关注上面那根折线的话)。

慢启动的执行过程如同上图左边的过程:

  • 初始时, c w n d cwnd cwnd的值为1个MSS。
    https://img-blog.csdnimg.cn/53a8cb891eee4ad6ac53d332498ec3df.png" alt="在这里插入图片描述" />
  • 在第1阶段开始时发送了一个数据包(因为 c w n d cwnd cwnd=1MSS),结束时收到了一个ACK。
    • 因为收到了一个ACK,所以 c w n d cwnd cwnd增加1个MSS,变成2个MSS。
      https://img-blog.csdnimg.cn/d5cb9fea03a94c93a7370acb1856dd99.png" alt="在这里插入图片描述" />
  • 在第2阶段开始时发送了两个数据包(因为 c w n d cwnd cwnd=2MSS),结束时收到了两个ACK。
    • 因为收到了两个ACK,所以 c w n d cwnd cwnd增加2个MSS,变成4个MSS。
  • 以此类推

https://img-blog.csdnimg.cn/c4d219efd8084b5583c62877582a47ea.png" alt="在这里插入图片描述" />
如上图,当 c w n d > s s t h r e s h cwnd > ssthresh cwnd>ssthresh时,转而使用拥塞避免算法。

https://img-blog.csdnimg.cn/2a36d982e5794f90a2fab13a46dba28f.png" alt="在这里插入图片描述" />
如上图,这三个状态(包括慢启动自身)当遇到超时后(遇到超时,说明网络已经拥塞了),都会执行:

  • s s t h r e s h ssthresh ssthresh设为 c w n d cwnd cwnd的一半。
    • s s t h r e s h ssthresh ssthresh变小,那么就会更快地从慢启动转到拥塞避免。
  • c w n d cwnd cwnd设为1MSS。
    • 让窗口回到初始值,并重新通过指数增长来探索到一个合理的窗口值。

拥塞避免

https://img-blog.csdnimg.cn/678d90ea2ac344c9bb8594690eaed161.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBAYW5saWFuNTIz,size_13,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述" />
如上图,在慢启动阶段, c w n d cwnd cwnd会快速增长,并且会确定一个可能小于64KB的 s s t h r e s h ssthresh ssthresh。如上图,整个慢启动过程中,可能遇到多次超时,每次超时后,将 s s t h r e s h ssthresh ssthresh减半,让 c w n d cwnd cwnd重新开始指数增长,最终 c w n d cwnd cwnd会超过 s s t h r e s h ssthresh ssthresh。值得注意的是,在离开慢启动前的最后一次指数增长过程中,是没有遇到过timeout的,也就是说,理想的窗口大小是大于等于这个 s s t h r e s h ssthresh ssthresh的(让窗口大小保持为 s s t h r e s h ssthresh ssthresh也可以,因为肯定不会造成网络拥塞。但是太过保守,有可能存在一个更大的值并且这个值也不会造成网络拥塞,所以,要让拥塞避免阶段来找到一个不那么保守的窗口大小)。

一旦超过了由慢启动阶段确定的 s s t h r e s h ssthresh ssthresh值,就意味着有更多可用的传输资源。如果立即全部占用这些资源,可能会使路由器出现严重丢包,从而使得网络不稳定。为了得到更多的传输资源同时不会影响其他TCP连接传输,所以我们要转而使用拥塞避免算法。
https://img-blog.csdnimg.cn/c229118bff1243acb9579229e9505a7f.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBAYW5saWFuNTIz,size_37,color_FFFFFF,t_70,g_se,x_16" alt="在这里插入图片描述" />
进入拥塞避免后, c w n d cwnd cwnd每次的增长值近似于成功传输的数据段大小,即每个RTT只将 c w n d cwnd cwnd的值增加一个MSS。从上面的折线图可以看到, c w n d cwnd cwnd呈线性增长。

拥塞避免的执行过程如同上图左边的过程:

  • 每收到一个ACK, c w n d cwnd cwnd增加 M S S ⋅ M S S c w n d MSS \cdot \frac{MSS}{cwnd} MSScwndMSS
  • MSS是每个数据包payload的大小, c w n d cwnd cwnd是窗口内可以发送数据的总和,所以在每个RTT刚开始时,会发送 c w n d M S S \frac{cwnd}{MSS} MSScwnd个数据包出来。
  • 正常情况下,在每个RTT快结束时,也会收到 c w n d M S S \frac{cwnd}{MSS} MSScwnd个ACK,那么 c w n d cwnd cwnd总共增加 M S S ⋅ M S S c w n d ⋅ c w n d M S S MSS \cdot \frac{MSS}{cwnd} \cdot \frac{cwnd}{MSS} MSScwndMSSMSScwnd即刚好一个MSS。
    https://img-blog.csdnimg.cn/743a8e9116c541309d4e2b621da983f3.png" alt="在这里插入图片描述" />

在拥塞避免阶段, c w n d cwnd cwnd的变化过程为:每个RTT内 c w n d cwnd cwnd线性(加性)增加1MSS,然后出现3个冗余ACK时, c w n d cwnd cwnd减半(乘性减)。因此,TCP拥塞控制常常被称为 加性增、乘性减(Additive-Increase, Multiplicative-Decrease,AIMD) 的拥塞控制方式。

快速恢复

能收到冗余ACK,说明网络可能有点拥塞,但是也没那么严重,所以进入到快速恢复这种中间状态,需要进一步确认网络的状况,以决定之后到底是回到慢启动还是拥塞避免。

快速恢复是一种中间状态,是因为只有一直收到冗余ACK才能维持这种状态:

  • 当处于慢启动、拥塞恢复状态时,只有收到3个冗余ACK后,才会进入到 快速恢复状态。此时,窗口近似减半(因为还加了3MSS)。
    https://img-blog.csdnimg.cn/efaef279f79d4f2e977c4d32a5bd45cc.png" alt="在这里插入图片描述" />
  • 当处于快速恢复状态本身时,只有继续收到冗余ACK才能保持拥塞恢复状态。其他事件都会使得状态变化。注意,窗口还在继续“膨胀”。
    https://img-blog.csdnimg.cn/df2e37b784f8435b9da43685b3e4307c.png" alt="在这里插入图片描述" />

处于快速恢复状态后,如果不再收到冗余ACK,那么其他事件将使得状态变化:

  • 如果超时,说明网络已经拥塞。那么由快速恢复进入到慢启动。
    https://img-blog.csdnimg.cn/ca38de67f36b406abe6533252608660b.png" alt="在这里插入图片描述" />
  • 如果收到new ACK,说明网络不拥塞,可以继续线性探索理想窗口大小。那么由快速恢复进入到拥塞避免。那么,窗口“收缩”到上一次窗口大小的一半值(看从上数第三张图,先做了ssthresh=cwnd/2,然后这里做了cwnd=ssthresh,所以这里是刚好减半)。
    https://img-blog.csdnimg.cn/cfeb6c62ebd34c449ffdd3826a52d7d3.png" alt="在这里插入图片描述" />

总结

  • 慢启动过程中,可能以数次的指数增长过程来找到一个 c w n d cwnd cwnd值,但这个 c w n d cwnd cwnd值可能太过保守。
  • 拥塞避免过程中,以线性增长过程来增加 c w n d cwnd cwnd值,以使得这个值既能相比慢启动结束时更大,也能保证整个网络不会拥塞。
  • 快速恢复则是一个中间状态,当连续收到3个及以上冗余ACK时会进入。如果timeout,那么回到慢启动;如果收到new ACK,那么回到拥塞避免。
  • 拥塞控制是加性增、乘性减的方式。

http://www.niftyadmin.cn/n/768156.html

相关文章

新版VSCode 1.60.0版 解决“无法将XXXX项识别为 cmdlet、函数、脚本文件或可运行程序的名称”的问题

环境 windows10系统&#xff0c;所以下面的那条配置"terminal.integrated.shell.windows"的后面是windows。 问题 前几天VSCode自动更新了&#xff0c;然后插件Task Explorer里面的任务就无法执行了。看了一下&#xff0c;发现了原因&#xff1a; 以前我在user配置…

Ubuntu16 通过gdebi安装搜狗输入法

环境 Ubuntu16.04 LTS已安装好了gdebi去搜狗输入法官网下载了搜狗输入法的deb包&#xff08;我的是sogoupinyin_2.4.0.3469_amd64.deb&#xff09; 输入法系统选择 需要选择为fcitx&#xff0c;一般默认就是这个了。 安装过程 右键单击搜狗输入法deb包&#xff0c;使用gdeb…

Visual Studio 2019 常用快捷键

注释 注释&#xff1a;选定区域&#xff0c;ctrl K&#xff0c;然后再ctrl C。 解注释&#xff1a;选定区域&#xff0c;ctrl K&#xff0c;然后再ctrl U。 多行编辑 Multi-caret selection caret就是指 那个一闪一闪的光标。 selection就是指 框住的一个单词。 CtrlA…

浅析——为什么UTF-16需要大端小端,而UTF-8不需要

文章目录为什么UTF-16需要大端小端什么是大端和小端内存中文件中大端形式小端形式为什么UTF-8不需要大端小端为什么UTF-16需要大端小端 我们使用编码网站查询“你”字的编码。 从上面的Unicode来看&#xff0c;我们知道&#xff0c;4F是数据位的高位&#xff0c;60是数据位的…

计算机网络 对Reno算法的优化——NewReno算法

Reno状态迁移图 实例分析Reno和NewReno 我们假设当前处于拥塞避免状态。如下图&#xff0c;[0-11]的这个窗口内的12个数据包从发送方发送。不过1、4数据包还没到达接收方就丢失了。一般情况下&#xff0c;发送方发送了seq0,len1的数据包后&#xff0c;接收方回复的ACK包为ack1…

TCP报文段的数据长度是如何计算得到的

TCP/IP结构分析 应用层把数据传给运输层&#xff0c;也就是给TCP协议。来自应用层的数据会被分割为MSS的大小&#xff0c;放到如下图的数据部分。 TCP报文段发送给网络层&#xff0c;也就是给IP协议。需要在TCP报文段的外面再套上IP协议的头部。如下图的数据部分&#xff0c…

计算机网络自顶向下.6e 第4章 网络层 知识点浅析

文章目录前言概述转发和路由选择网络服务模型虚电路和数据报网络虚电路网络数据报网络路由器工作原理输入端口交换结构输出端口何处出现排队路由选择控制平面网际协议&#xff08;IP&#xff09;&#xff1a;因特网中的转发和编址数据报格式&#xff08;datagram&#xff09;IP…

draw.io 表格添加行列

基本操作 如上图&#xff0c;点击 生成如上表格 单击表格&#xff0c;会出现。依次是&#xff1a; 左侧插入列。如果选中的是整个表格&#xff0c;则在最左侧添加。如果选中的是某个单元格&#xff0c;则在这个单元格所在列的左侧&#xff0c;添加列。右侧插入列。删除列。如…