Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

超时与重传

复习

  • 序号与确认:接收方用确认告知收到的进度
  • TCP 为什么需要连接:可靠传输需要双方维护状态
  • 三次握手:连接建立之后才开始传输数据

TL;DR

  • 发了却没收到确认,发送方就需要重传
  • 重传要等多久,由超时时间决定
  • 超时太短会误重传,太长又反应迟钝
  • 根据实际往返时间动态估计超时,是常见做法

正文

  有了确认,发送方知道“对方收到了没有”。可如果确认迟迟不来,该怎么办?它不能一直等下去,总得有个“等多久算丢”的期限。

一个定时器

  发送方每发出一段数据,就启动一个重传定时器。两种结局:

  • 在定时器到点之前收到确认:撤销定时器,继续发后面的
  • 定时器到点仍未收到确认:认定该段可能丢了,重传

  这机制本身不难,难的是——该等多久?

等多久的两难

  超时时间设得不好,会有两种麻烦:

  • 太短:数据其实没丢,只是确认在路上慢了点,发送方就急着重传,白白浪费带宽,还让接收方收到重复段
  • 太长:真丢了也要干等很久才重传,整体速度被拖慢,网络空着也不干活

  所以,没有哪个固定的秒数万全。网络时延是变化的,合适的超时也应该跟着变。

让超时自己适应

  一个自然的思路是:先测量实际的往返时间(RTT),再据此估算超时。

  做法大致是:为每一段数据记录“发出时刻”和“收到确认时刻”,两者相减得到这次往返花了多久;把这些测量值平滑一下,再留出一点余量(防止偶然波动),就得到当前的超时时间。

  网络快,测得快,超时就短;网络慢,超时自动变长。与其拍一个死板的数字,不如让机制自己观察、自己调整。

不必干等

  还有一种情况:接收方发现中间丢了一段,后面却收到了。它会在每次收到“缺口之后”的数据时,反复回同一个确认,等于在喊:“我还在等那一段!”

  发送方连续收到几个这样的重复确认,就能猜到“应该是丢了,赶紧重传吧”,不必等到定时器到点。这叫快速重传,是超时机制的有效补充。

  连续发、放心发,靠的是另一个工具——滑动窗口。

思考题 1

  超时时间设得太短或太长,各自会有什么问题?

思考题 2

  为什么超时时间应该根据实际往返时间估计,而不是固定一个数?

小结

知识点

  • 发送方用重传定时器判断是否重传
  • 超时设置存在“太短误传、太长迟滞”的两难
  • 依据测量的往返时间动态估计超时
  • 快速重传可在超时前提前重发

参考资料

  1. Wikipedia(zh):传输控制协议:超时与重传机制
  2. Wikipedia(zh):往返时间:数据往返一次所需的时间

思考题答案(仅供参考)

思考题 1

  太短时,明明没丢的数据会被误判为丢失而重传,浪费带宽并造成重复;太长时,真丢了也要等很久才重传,传输效率被拖慢。两种都会损害性能,所以需要动态、合适的取值。

思考题 2

  因为网络时延本来就随时间波动,固定一个数无法同时适应快网和慢网。测量实际往返时间并加以平滑和留余量,能让超时随网络状况自动调整,减少误重传又不至于反应迟缓。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪