我曾经firefox
访问过在我的 LAN 上的计算机上运行的 Web 服务器。我注意到 TCP 有时不会确认收到的数据包。例如,在以下捕获的数据包中:
https://docs.google.com/file/d/0B-LaBUj9KtQhS0RYNXF1RjZTa2M/edit?usp=sharing
第7、9、11个数据包是重复的ACK,浏览器收到了TCP数据包6、8、10,但是浏览器TCP堆栈没有确认收到的数据包,为什么?
答案1
但事实并非如此。
它只是确认流中的每个字节,这是完全不同的。由于某种原因,接收方的 TCP(浏览器在其上运行的 TCP)错过了第 6 个段。由于接收方立即请求重新传输,因此它一定是在校验和不匹配的情况下收到了该段。
随后收到的所有段(8、10、12)都是无序段,并触发重复确认,目的是请求重新传输段 #6。由于接收方和发送方之间的通信路径会经历一些延迟,发送方会稍晚注意到这一点,从而缩短其管道长度(又称拥塞窗口)并重新传输段 #6 中包含的数据。
然后,在段 #15 中发生了另一件有趣的事情:接收方没有发送对 8、10、12 的累积确认,而只确认了段 #14,这意味着它已经丢弃了 8、10 和 12,要么是因为它们也容易受到数据损坏,要么是因为它是一个非常简单的 TCP 实现。您可以在 wireshark 中启用 TCP 校验和评估,(由于操作系统使校验和字段对以太网卡无效,因此它在每个传出段上都会失败)并且它证实了前一种解释:8、10、12 上的校验和错误。路径上一定有一个非常嘈杂的链接。
答案2
是的。
你可能会看到TCP 延迟确认,接收方最多可以延迟 500 毫秒,以便发送组合 ACK 数据包以确认已收到的多个数据包。当您有大量数据包并且不特别关心延迟时,这有利于减少开销。
这会增加感知延迟,因此,您会发现许多针对游戏的“TCP 修复”都禁用了此功能:通过将 TCP_ACKNOWLEDGE_DELAY 设置为 0,Windows 将立即发送所有 ACK,而不是尝试对它们进行分组。这样做的缺点是会产生更多的网络流量,而好处不大。它看起来降低了延迟,但数据包的发送速度并没有加快。