在对另一个问题进行故障排除时,我注意到 TCP 关闭存在奇怪的模式。
数据包:http://www.cloudshark.org/captures/7590ec4e6bef
发生的事情是,由于某些奇怪的原因,关闭序列的最后几个数据包被重新传输。模式在cloudshark 链接中,但为了方便后人,这里是摘要:
- 来源 -> 同步
- 目标->确认
- 源 -> SynAck
- 数据
- 数据
- 来源 -> Fin/Ack
- 目标 -> Psh/Ack (6)
- 目标 -> Fin/Ack
- 源 -> 确认 (7)
- 源 -> 确认 (8)
- [此时双方的连接应该都关闭了。但事实并非如此。]
- [+200ms] 目标 -> Fin/Ack
- 源 -> 确认 (8 & 12)
目标系统上的某个东西在重新发出 Fin/Ack 数据包之前等待了 200 毫秒。这在多个事务中非常一致。更糟糕的是,这种模式在事务的两侧都重复出现:它出现在两个主机的捕获中。它并不像 Fin/Ack 数据包在某处被丢弃并被重新传输那么简单。或者它确实被丢弃了,但在某种程度上多于在哪里tcpdump
运作。
200ms 的延迟让我认为这里涉及到了 TCP 延迟确认,但我无法弄清楚为什么会这样。
是高于 tcpdump甚至一件事?
这是 RHEL6 系统的正常连接模式吗?
答案1
请注意,您捕获的帧 #2 中的 PSH/ACK 数据包携带 37 个字节的数据。它不是对来自 10.232.16.133 的 FIN 请求的响应。响应位于帧 #3 中,而 ACK 位于帧 #5 中。
现在似乎发生的情况是,最后一个 ACK 未到达目的地,因此在帧 #3 中发送的 FIN/ACK 将在帧 #6 中重新传输。您在此处看到的 ~200 毫秒延迟不是延迟的 ACK,而更可能是重新传输超时。您应该能够通过查看连接另一端的数据包捕获来验证这一点,您永远不应该看到最后一个 ACK 到达。
如果您在所有连接上(可能在两个方向上)一致地看到这种行为,我想到的一个解释是,路径中的一些状态保持数据包过滤器正在吞噬最后的 ACK。