重传定时器:每段一个还是一个全局定时器?

网络工程 tcp 协议论
2022-03-04 21:14:53

TCP 使用各种机制来检测数据包丢失并决定何时重新传输段。在这个问题中,我问的是基于超时的重传,其中 TCP 在某个计时器到期时重新传输某些段。这是一个单一的全局重传定时器,即重传队列中的所有段都有一个定时器,还是队列中的每个段都有一个独立的重传定时器?

具体来说,我认为可能的(互斥)选项是:

  • 选项 A:有一个单一的全局计时器。
    • 当一个段被发送时,如果定时器没有被激活,它就会被启动,并且该段的副本被放置在重传队列中。
    • 当一个确认该特定段(可能在其他段中)的 ACK 到达时,它将从重传队列中删除。
    • 每当任何ACK 到达时,无论它正在确认什么数据,重传计时器都会重置。
    • 当计时器到期(在那个时间窗口内没有收到任何 ACK)时,在重传队列的前面重新传输一些(可能只是一个)段并重置计时器(可能具有更长的持续时间)。
    • 当重传队列为空时,取消定时器。
  • 选项B:重传队列中的每个段都有自己独立的定时器。
    • 当一个段被发送时,一个副本被放置在重传队列中,一个新的重传定时器与之相关联,并且定时器被启动。
    • 当一个确认该特定段(可能在其他段中)的 ACK 到达时,它将从队列中删除,并取消其关联的计时器。
    • 当特定段的计时器到期时,重新传输该段并重置计时器。

我正在考虑可能是这种情况的其他选项,但它们是这两个选项的变体。

这就是我的困惑是如何产生的。首先,这个答案说:

根据 RFC 793,TCP 在其重传队列中的每个段使用一个重传计时器。

这支持选项 B。最近,在我正在学习的网络系统课程中,讲师以一种似乎暗示只有一个计时器的方式提到了这种机制(选项 A)。我问了他这个具体的问题,他确认只有一个计时器,并且收到任何 ACK 都会重置它。当然,这与我之前的想法相矛盾,因此我尝试自己访问主要资源以试图阐明这一点。RFC 793的原始版本在第 2.6 节中提到了以下内容(重点是我的):

当 TCP 传输包含数据的段时,它会将副本放入重传队列并启动计时器当收到对该数据确认时,将从队列中删除该段。如果定时器用完之前没有收到确认,则重传该段。

此外,在同一文档的第 3.9 节中,在“RETRANSMISSION TIMEOUT”标题下,这样写:

对于任何状态,如果重传队列中某个段的重传超时到期,则再次发送重传队列前面的段,重新初始化重传计时器,然后返回。

就其措辞而言,它似乎在重传队列中为每个段指定一个独立的计时器(选项 B);虽然,老实说,这对我来说很模糊。

但是,最新版本的 RFC 793不包括第一个引用的段落(或任何等效的,据我所知),但第二个仍然存在。再一次,RFC 6298 的第 5 节内容如下:

5. 管理 RTO 定时器

实现必须以这样一种方式管理重传计时器,即一个段永远不会过早重传,即,在该段的先前传输之后少于一个 RTO。

以下是管理重传定时器的推荐算法:

  • (5.1) 每次发送包含数据的数据包(包括重传)时,如果定时器没有运行,则启动它运行,使其在 RTO 秒后到期(对于 RTO 的当前值)。

  • (5.2) 当所有未完成的数据都被确认后,关闭重传定时器。

  • (5.3) 当收到确认新数据的 ACK 时,重新启动重传计时器,使其在 RTO 秒后到期(对于 RTO 的当前值)。

当重传计时器到期时,请执行以下操作:

  • (5.4) 重传尚未被 TCP 接收方确认的最早段。

  • (5.5) 主机必须设置 RTO <- RTO * 2(“退出计时器”)。上面 (2.5) 中讨论的最大值可以用来为这个加倍操作提供一个上限。

  • (5.6) 启动重传定时器,使其在 RTO 秒后到期(对于 5.5 中概述的加倍操作后的 RTO 值)。

[...]

这显然指定了选项 A。但它说这只是推荐的算法,所以它可能不是“核心”TCP 标准的一部分?

我非常困惑。你能用权威的参考资料帮我解决这个问题吗?

1个回答

请注意,您链接到的“最新版本”只是草稿,没有真正的含义。

RFC 793 实际上并没有具体说明这一点——早期的 RFC 就是这样,留有很大的优化空间。计时器变体特定于给定的实现。但是,我们可以放心地假设大多数实现都使用您的选项 A - 一个单一的、特定于套接字的计时器。

请注意,仅在传输数据时才重新启动计时器,而不是在其他情况下为空的 ACK 段。