TCP 窗口探测

TCP 窗口探测

当我最初在网络 SE 中询问时,我被引荐到这个网站。

我对 TCP 中的 rwnd 广告有几个问题。我读过 RFC,但仍然没有答案(或者我可能错过了一些东西)。也许有些答案与实现有关 - 在这种情况下,请根据您的经验回答,因为我想知道一般情况下会发生什么。

TCP标准规定如下:

即使发送窗口为零,发送方 TCP 也必须准备好接受来自用户的数据,并发送至少一个八位字节的新数据。

我猜测,造成这种情况的原因是窗口探测消息包含一个八位字节的数据。然而,这让我想到:

  1. 我没有看到标准中规定探测数据包必须包含一个八位字节的新数据。还有其他方法可以探测窗口大小吗?

  2. 如果这是唯一的方法,我想知道为什么重新发送旧段(使用旧序列号)是不够的。接收方是否只需确认特定时刻窗口内的数据(这意味着旧数据不一定被确认),这意味着我们必须将探测数据包视为该规则的例外?

  3. 一般来说,当窗口增大时,接收方会通知发送方吗?它必须这样做吗(我理解确认可能会丢失,因此发送方可能必须进行探测)?

  4. 探测数据包是否仅在时发送,window = 0或者是否可以在之前发送?

答案1

我认为其原因是窗口探测消息包含一个八位字节的数据。

需要明确的是,窗口探测数据包没有特殊的数据包格式、标头或其他标识符。TCP 在需要探测窗口时只会发送标准 TCP 数据包。它只是将该 TCP 数据包中的用户/应用程序数据限制为一个八位字节。

  1. 我还没有看到标准中规定探测数据包必须包含一个八位字节的新数据。

您刚刚引用了标准中的声明,即探测数据包必须至少包含一个八位字节的新数据,不是吗?如果您需要其他声明,您会在 RFC 793 和 RFC 1122 中找到声明,这些声明提醒您没有新应用程序数据的 Ack 无法可靠地传输(这意味着您必须传输一些新数据才能知道它是否通过了)。

有不同的方法来探测窗口大小吗?

可以想象,TCP 标准的作者可以想出其他方法,但您引用的方法是他们在标准中提供的唯一方法。

  1. 如果这是唯一的方法,我想知道为什么重新发送旧段(带有旧序列号)是不够的。

这不是是否足够的问题,而是最佳方法的问题。如果你没有其他数据要发送,则无需探测窗口。如果你有进一步的数据要发送,为什么不使用探测窗口,而不是浪费带宽在先前发送的(大概是 Ack'd)数据上?

接收方是否只需确认某一时刻窗口内的数据(这意味着旧数据不一定会被确认)

接收方应该只确认它收到的最新数据,即与自开始以来收到的所有数据连续的数据(所谓连续,是指如果它因为错过一个或多个数据包而出现漏洞,但收到了后续数据包,则它无法确认后续数据包;它必须继续确认第一个漏洞之前的最后一个序列号)。

  1. 一般来说,当接收方的窗口尺寸增大时,它会通知发送方吗?

是的,一般来说,接收方会在每次 Ack 时通知发送方窗口大小更新。

此外,在 RFC 793 第 43 页的“窗口管理建议”下,作者建议 TCP 接收方“在窗口较大时发送另一个带有新窗口信息的确认”。此 RFC 早于定义 MAY/SHOULD/MUST 术语标准的 RFC 2119,但根据 RFC 2119 的要求级别指导,此建议似乎被视为 SHOULD。

它必须这样做吗(我理解确认可能会丢失,所以发送方可能无论如何都必须进行探测)?

我不知道有任何 RFC 更新 RFC 793 会使这种行为成为必须的。

探测数据包是否仅当窗口 = 0 时才发送,还是可以提前发送?

如果窗口不为零,那么单数据字节 TCP 段实际上不会被视为探测。例如,如果我有一个 telnet 连接,该连接正在向远程主机发送单个击键,则每个击键可能会作为单数据字节 TCP 段发送。在像 telnet 这样的情况下,即使窗口大于 0 或 1,也可以发送这些 TCP 段,但它们不会被视为探测。

答案2

这是基于Spiff 的回答,但补充的内容比评论中的内容要多。请注意,2022 年 8 月RFC9293最终取代了原始的 TCP 规范,它包含所有 MUST/SHOULD/MAY 语言。

Q1. 我没有看到标准中规定探测数据包必须包含一个八位字节的新数据。

以下要求不限于一个八位字节,在原始 TCP 规范中RFC793并逐字复制到RFC9293中:

When the receiving TCP peer has a zero window and a segment arrives, it must
still send an acknowledgment showing its next expected sequence number
and current window (zero).

Q2. 我想知道为什么重新发送旧段...是不够的

这不是最有效的方法(如果窗口变得足够大,八位字节仍然必须被丢弃)。但它会起作用,因为 TCP 拥塞控制规范总是这么说RFC5681现在说:

A TCP receiver SHOULD send an immediate duplicate ACK when an out-of-
order segment arrives.

Q3. 一般来说,当接收方的窗口增大时,它会通知发送方吗?

我假设您的意思是接收方窗口增大是因为接收应用程序消耗了接收缓冲区中的一些数据。那么,我认为规范中没有要求发送 ACK 来通知这一点。因此需要窗口探测来引出 ACK。

Q4. 仅当窗口 = 0 时才发送探测数据包吗?

是的,根据定义。因为如果在窗口 = 0 之前发送了一个八位字节的数据包,那么它将只是一个恰好为一个八位字节大小的普通数据包。

相关内容