小码哥《网络协议从入门到底层原理》笔记(八):TCP可靠传输、流量控制、拥塞控制

957 阅读5分钟

我的Github地址

小码哥《恋上数据结构与算法》笔记

极客时间《iOS开发高手课》笔记

iOS大厂面试高频算法题总结

iOS面试资料汇总

可靠传输

停止等待ARQ协议

  • ARQ(Automatic Repeat-reQuest)自动重传请求

连续ARQ协议 + 滑动窗口协议

  • 滑动窗口的大小由接收方缓存大小决定。

SACK(选择性确认)

  • TCP通信过程中, 如果发送序列中间某个数据包丢失(比如1,2,3,4,5中的3丢失了)
  • TCP会通过重传最后确认的分组后续的分组(最后确认的是2,会重传3,4,5
  • 这样原先已经正确传输的分组也可能重复发送(比如4,5),降低了TCP性能
  • 为改善上述情况,发展出了SACK(Selective Acknowledgement,选择性确认)技术
    • 告诉发送方哪些数据丢失, 哪些数据已经提前收到
    • 使TCP只重新发送丢失的包(比如3), 不用发送后续所有的分组(比如4,5
  • SACK信息会放在TCP首部的选项部分
    • Kind:占1字节。值为5代表着是SACK选项
    • Length:占1字节。表明SACK选项一共占用多少字节
    • Left Edge:占4字节,左边界
    • Right Edge:占4字节,右边界
  • 一对边界信息需要占用8字节,由于TCP首部的选项部分最多40个字节,所以
    • SACK选项最多携带4组边界信息
    • SACK选项的最大占用字节数 = 4 * 8 + 2 = 34

疑问

  • 若有个包重传了N次还是失败,会一直持续重传到成功为止么?
    • 这个取决于系统的设置,比如有些系统,重传5次还未成功就会发送reset报文(RST)断开TCP连接
  • 如果接收窗口最多能接收4个包,但发送方只发了2个包,接收方如何确定后面还有没有2个包?
    • 等待一定时间后没有第3个包,就会返回确认收到2个包给发送方
  • 为什么选择在传输层就将数据“大卸八块”分成多个段,而不是等到网络层再分片传递给数据链路层?
    • 因为可以提高重传的性能
    • 需要明确的是:可靠传输是在传输层进行控制的
      • 如果在传输层不分段,一旦出现数据丢失,整个传输层的数据都得重传

      • 如果在传输层分了段,一旦出现数据丢失,只需要重传丢失的那些段即可

流量控制

  • 如果接收方的缓存区满了,发送方还在疯狂地发送数据
    • 接收方只能把收到的数据包丢掉,大量的丢包会极大地浪费网络资源
    • 所以要进行流量控制
  • 什么是流量控制?
    • 让发送方的发送速率不要太快,让接收方来得及接收处理
  • 原理
    • 通过确认报文中窗口字段来控制发送方的发送速率
    • 发送方的发送窗口大小不能超过接收方给出窗口大小
    • 当发送方收到接收窗口的大小为0时, 发送方就会停止发送数据

疑问

  • 有一种特殊情况
    • 一开始, 接收方给发送方发送了0窗口的报文段
    • 后面, 接收方又有了一些存储空间,给发送方发送的非0窗口的报文段丢失了
    • 发送方的发送窗口一直为零,双方陷入僵局
  • 解决方案
    • 当发送方收到0窗口通知时,这时发送方停止发送报文
    • 并且同时开启一个定时器,隔一段时间就发个测试报文去询问接收方最新的窗口大小
    • 如果接收的窗口还是为0,则发送方再次刷新启动定时器

拥塞控制

  • 拥塞控制
    • 防止过多的数据注入到网络中
    • 避免网络中的路由器或链路过载
  • 拥塞控制是一个全局性的过程
    • 涉及到所有主机, 路由器
    • 以及与降低网络传输性能有关的所有因素
    • 是大家共同努力的结果
  • 相比而言, 流量控制是点对点通信的控制

慢开始

  • 关键名词
    • MSS(Max Segment Size):每个段最大的数据部分大小
      • 在建立连接时确定
    • rwnd(receive window):接收窗口
    • cwnd(congestion window):拥塞窗口
    • swnd(send window):发送窗口
      • swnd = min(cwnd,rwnd)
  • cwnd的初始值比较小,然后随着数据包被接收方确认(收到一个ACK
    • cwnd就成倍增长

拥塞避免(已废弃,使用下文说的快恢复)

  • ssthresh(slow start threshold): 慢开始阈值, cwnd达到阈值后, 以线性的方式增加
  • 拥塞避免(加法增大):拥塞窗口缓慢增大,以防止网络过早出现拥塞
  • 乘法减小:只要网络出现拥塞,把ssthresh减半,于此同时,执行慢开始算法(cwnd又恢复到初始值)
    • 当网络出现频繁拥塞时,ssthresh值就下降的很快

快重传

  • 接收方
    • 每收到一个失序的分组后就立即发出重复确认
    • 使发送方及时知道分组没有到达
    • 而不是等待自己发送数据时才进行确认
  • 发送方
    • 只要连续收到三个重复确认(总共4个相同的确认),就应当立即重传对方尚未收到的报文段
    • 而不必继续等待重传计时器到期后再重传

快恢复

  • 当发送方连续收到三个重复确认,就执行“乘法减小”算法,把ssthresh减半
    • 与慢开始不同之处是现在不执行慢开始算法,即cwnd现在不恢复到初始值
    • 而是把cwnd值设置为ssthresh减半后的数值
    • 然后开始执行拥塞避免算法("加法增大"),使拥塞窗口缓慢地线性增大

发送窗口的最大值

  • 发送窗口的最大值:swnd = min(cwnd,rwnd)
  • rwnd < cwnd时,是接收方的接收能力限制发送窗口的最大值
  • cwnd < rwnd时,是网络的拥塞限制发送窗口的最大值