TCP 流量控制问题让我抓狂

网络工程 通讯协议 线鲨 转储
2021-07-22 05:49:51

这是我从 FTP 服务器下载 10Mb 文件时捕获的 TCP 会话。服务器的 ICW 为 10x MSS,因此这意味着服务器最初可以发送 10 个段而不会收到来自客户端的 ACK。

在此处输入图片说明

话虽如此,每两个段都被实时确认,服务器已将所有10个段发送给已经确认所有段的客户端。现在,服务器从 15:40:31:864 到 15:40:31:901 等待了超过 50 毫秒,直到它开始发送新段。

我想知道,为什么服务器暂停发送更多的段,尽管所有的段都已经被确认?我知道它在等待 RTO 值,但是为什么服务器在收到所有 ACK 后还要这样做呢?

更新1:

谢谢您的回答。但是,我需要在这里详细说明。

在此处输入图片说明

以上是流的 RTT,您可以看到第一部分(直到 SEQ# 2600000)的平均 RTT 约为 30 毫秒。因此,最初在服务器端,cwin 已经填充并填充了 10 个准备发送的段。

想必:

前两个数据包已在 -> 15:40:31.842 从服务器发送,并已在客户端(我正在捕获)在 -> 15:40:31.862 同时收到,客户端发送了一个在 -> 15:40:31.862 延迟到服务器的 ACK 并且大概在 -> 15:40:31.882 被服务器收到

这时候cwin会滑动,去掉旧的两个segment,腾出空间给客户端发送两个新的segment,除非cwin或者rwin的cwin已经准备好发送客户端已用尽,这不是我们的情况,或者服务器正在等待 ACK,这也是无效的。

因此,服务器有 10 个段,发送了 8 个,前 2 个得到 ACK,将 cwin 向右滑动,得到两个新段。现在 cwin 有 10 个段要再次进行,不可阻挡。我的问题是,为什么服务器在这个阶段暂停传输?

更新2:

您可以查看流的第一部分的以下 tcptrace:

在此处输入图片说明

斜率是放松的(不是陡峭的),你可以看到每大约 50 毫秒有一次无缘无故的停顿。

但是,在连接的中间部分:

在此处输入图片说明

坡度更陡,中间没有间隙,也没有停顿。考虑到两个部分的 RTT 相同,您可以通过 RTT 图确认这一点

2个回答

假设这是客户端捕获,您需要考虑客户端和服务器之间的往返延迟,因此这些时间戳显示客户端何时发送/接收数据包,而不是服务器何时接收/发送它们。

例如,如果客户端在 T=0ms 发送 ACK,它在 T=50ms 到达服务器,假设即使服务器在不到 1ms 响应,响应也在 T=50ms 发送并且它在例如 T= 到达客户端110 毫秒(因为延迟可能不是恒定的,而且每个方向也可能不同)。因此,在您的客户端捕获中,您会在 T=0 毫秒时看到 ACK,在 T=110 毫秒时看到下一个数据,但这并不意味着服务器等待 110 毫秒来响应。简单来说就是(ACK的传输+服务器上的处理+数据的传输)的总时间=110ms。

因此,要确定,您需要在服务器上进行捕获(最好与客户端上的捕获同时进行)。如果没有服务器端捕获,我们只能猜测,但您的客户端和服务器之间的延迟似乎很可能约为 20毫秒,因此 RTT(往返时间)约为 40毫秒(但同样,延迟每个数据包可以不同)。

编辑:上述 20/40ms 的值基于您提到的时间戳,15:40:31:864 到 15:40:31:901(实际上只有 37ms),但实际上您需要查看第一个 ACK (在 15:40:31.862 发送,第 33 帧)和第 47 帧中的数据包,在 15:40:31.922 收到,因此 RTT 有 60 毫秒。


更新 1 和 2 后编辑

正如评论中已经提到的,我不认为服务器发送 8 个段然后暂停,我认为它发送了 10 个段(帧 31-32,34-35,37-38,40-41,43-44) ,然后它暂停,直到它收到第 33 帧(对前 2 个段的 ACK);收到此 ACK 后,它发送第 47 帧和第 48 帧等。同样,这是一个假设,需要服务器端捕获来确认,但这对我来说似乎是很正常的预期行为。

至于稍后在连接中发生的事情,在不查看实际捕获的情况下,可以合理地假设由于TCP 慢启动,cwin 的大小会增加,因此服务器可以在等待 ACK 之前发送更多段,并且在某些时候点 cwin 足够大,服务器可以在不等待 ACK 的情况下继续发送数据(只要 ACK 继续以相对稳定的速率接收)。

首先,突出显示的数据包是另一个对话的一部分。你应该过滤。但是,RTT 更接近 50ms,这就是暂停长度?可能发生的情况是应用层一次向 TCP 发送一个块,并在发送下一个块之前等待 ACK。查看 PSH 位之间的 SEQ# 增加了多少,这就是应用程序发送块大小。