TCP拥塞控制

建立TCP连接的双方都维护着一个缓冲区, 当缓冲区满了的时候再接收数据会造成溢出, 就会丢弃数据.
因此, 为了消除这种现象, TCP提供了流量控制服务.

另外, 由于网络带宽等因素的限制, 发送方发出的数据并不能总是顺利地到达接收方, 当路由器缓冲区
满了的时候, 再有数据到达会被丢弃, 从而造成数据丢失, 针对这种现象, TCP同样提供了拥塞控制服务

流量控制

如上所述, TCP连接的建立会产生两个缓冲区 RcvByffer, 我们假设建立连接的双方为A和B
TCP通过让发送方A维护一个称为接收窗口 rwnd 的变量来提供流量控制

定义:

  • LastByteRead : 主机B上缓冲区被上层读取的最后一个字节编号
  • LastByteRcvd : 主机B缓冲区接收的最后一个字节编号

为了不使缓冲区溢出, 下面的式子必须成立:

LastByteRcvd - LastByteRead <= RcvByffer

则接收窗口表示为:

rwnd = RcvByffer - (LastByteRcvd - LastByteRead)

其实就是接收方缓冲区的空闲空间

因此, 对于发送方A来说, 其必须保证已经发送出去,但是未收到ACK的数据 <= rwnd

为了让发送方A时刻满足上述条件, 接收方B每次回复A时会将接收窗口大小告诉A.
但是, 有一个问题, 假如B告诉A接收窗口为0, A不再发送数据, 但是之后B的缓冲区有空闲了, 由于没有数据到达, B无法告知A缓冲区可以接收新的数据, A将一直等待.

为了解决上述情况, TCP规范规定, 当接收方B告知A缓冲区已满, A继续向B发送一个字节的数据, B将会收到这个数据,并在缓冲区有空时通過確認报文告知A.


拥塞控制

同流量控制类似, 发送方也通过维护一个额外变量拥塞窗口 cwnd来提供拥塞控制服务.
因此, 发送方已经发送出去,但是未收到ACK的数据 <= MIN{rwnd, cwnd}

再介绍拥塞控制之前先说说哪些情况对于TCP发送方来说意味着出现拥塞

  • 当出现超时情况时, 认为发生了丢包, 需要进行拥塞控制
  • 当收到连续的3个冗余ACK时, 可能发生了丢包, 也意味着拥塞

而当收到正常的ACK时, 发送方认为网络状况良好, 会提高发送速率

TCP拥塞控制算法包括3个部分:慢启动, 拥塞避免和快速恢复

慢启动

当一条TCP连接刚开始时, 发送方不知道当前的网络状况如何, 因此最好的办法是试探, 先发送一个 MSS (TCP报文数据字段最大值), 如果正常收到 ACK, 下次发送 两个 MSS, 如果还是正常, 再下次就发送 四个 MSS。。。。

所以慢启动算法可以描述如下:
发送方最初将 cwnd 设置为一个MSS 大小, 当收到正常的ACK时, 将 cwnd 增加一个 MSS, 一次性发送 2*MSS . 然后再每收到一个正常ACK时 cwnd 增加一个 MSS, 当之前发送的两个 MSS 都收到 ACK后下次发送时就一次性发送 4*MSS . 如此, 在慢启动阶段, cwnd 大小会呈 2^n 次增长。 当然, 这种指数增长状态不会一直持续下去。

慢开始 状态不会一直持续下去, 网络的承载能力总是有限的, 因此有个变量 ssthresh慢启动阈值 来限制慢启动状态的 cwnd 增长。

阈值就相当与分界线, 在分界线以下是一个状态即 慢启动, 在分界线以上则转为 拥塞避免 状态。阈值的设置有下面两种情况:

  • 情况1: 当发生一个 TIME_OUT 丢包时, 发送方 将状态量 ssthresh(慢启动阈值) 设为 cwnd/2 , 然后置 cwnd 为 1*MSS. 继续慢启动开始的增长状态。
  • 情况2: 当检测到3个冗余ACK时, 说明可能发生了丢包(注意, 丢包一定产生3个ACK, 但3个ACK不一定就是丢包). TCP 执行快速重传, 并进入快速恢复状态

我们看到,不管是哪种情况, 只要发生了,就认为当前网络状况不太好,然后就将慢启动阈值 ssthresh 设置为当前拥塞窗口的一半。区别在于不同状况下新的拥塞窗口初始大小不一样。

拥塞避免

前面说到, 当 cwnd >= ssthresh 时从慢启动转向拥塞避免状态, 此时对cwnd的增长不再是指数的, 而是线性的.

在拥塞避免状态, 当收到正常ACK时, cwnd增加 一个 MSS*(MSS/cwnd) 大小 ,当出现下面两种情况时, 就会结束拥塞避免状态:

  • 情况1:发生TIME_OUT , 处理方式和慢启动一样, ssthresh = cwdn/2cwnd = 1*MSS, 并转向慢启动
  • 情况2:收到3个A冗余ACK, ssthresh = cwdn/2cwnd = ssthresh+3*MSS, 处于快速恢复状态。

快速恢复

快速恢复算法是后来对 TCP 拥塞控制进行改进而在慢启动拥塞避免 基础上增加的算法。

快速恢复算法是用来应对包丢失的情况。 当接收方收到乱序的数据包,接收方向发送方发送一个 “请求再次发送丢失的包” 的消息,当请求消息达到三次则开始快速恢复算法。

快速恢复算法之所以不同与慢开始的依据是: 既然发送方能收到接收方的连续三个请求重发的消息, 说明网络拥塞状况并不严重,那就没必要把拥塞窗口一下子降低到一个 MSS 大小。而是把慢启动阈值设为当前拥塞窗口的一半, 并将拥塞窗口初始大小设为 阈值 + 3个MSS 大小。多出的 3个 MSS 理由是:发送方既然已经收到接收方发来的3个重发请求, 说明已经有三个分组被接收方成功接收了,因此窗口可以适当增加3个 MSS

快速恢复算法开始后,发送方向接收方发送之前丢失的包, 当这个包的 ACK 到达后就会重新设置 cwdn 然后转为 拥塞控制 状态。所以说快速恢复状态的持续时间很短。
具体描述为:
TCP发送方会将阈值和拥塞窗口的值分别设置为 ssthresh = cwdn/2, cwnd = ssthresh+3*MSS

- 最终当丢失报文段的第一个ACK到达发送方时,TCP发送方**再次降低cwdn**进入拥塞避免 此时 `cwdn = ssthresh`.
- 而当出现TIME_OUT时, 则令 `ssthresh = cwdn/2`, `cwdn=1*MSS` 转向慢启动

总结:

  • 无论在哪种状态, 当发生TIME_OUT时 ,令 ssthresh = cwnd/2, cwdn = 1*MSS 转向慢启动.
  • 无论在哪种状态, 当发生3个冗余ACK时, 令 ssthresh = cwnd/2, cwnd = ssthresh + 3*MSS, 转向快速恢复
  • 处于慢启动时, 当 cwnd >= ssthresh 会转向 拥塞避免;
  • 处于快速恢复时, 当丢失报文段的ACK第一次到达时,令 cwnd = ssthresh 转向拥塞避免

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值