我有一个应用程序,它可以从主机 A 向主机 B 连续无间隙地发送 100 条 186 字节(不包括标题)的 TCP 消息。
我运行 tcpdump 来捕获主机 A(发送方所在地)上的数据包,并且我注意到在几条消息(比如 9 条)之后,接下来的 ~25 条消息合并为一条 5+K 消息。
我已经通过发送方应用程序中的 setsockopt() 关闭了 Nagle 算法,并且计算出的 TCP 窗口始终超过 14K 字节。因此,看起来前 9 条消息并没有填满主机 B,主机 B 也没有要求主机 A 减速。
关于如何找出 TCP 消息合并的原因,有什么提示吗?
谢谢!
答案1
我有一个应用程序,它可以从主机 A 向主机 B 连续无间隙地发送 100 条 186 字节(不包括标题)的 TCP 消息。
那么你发送消息的速度可能比网络传输的速度要快,在这种情况下,当发送方的 TCP 实现准备好在网络上发送数据包时,可能会有多条消息排队,在这种情况下,它会在单个 TCP 段中发送尽可能多的消息。TCP 协议提供字节流服务,不消息边界的概念,所以允许这样做。
我已经开启了 Nagle 算法
Nagle 算法 明确地执行你所说的发送方 TCP 正在执行的操作:
Nagle 算法的工作原理是将多个小的传出消息合并起来,然后一次性发送。
所以把它在不会阻止这种情况。转动它离开在某些情况下可能会阻止这种情况,但考虑到您的应用程序发送大量消息,它可能无法阻止这种情况。
(即,“为什么发送方的 TCP 合并消息?”的答案是“因为它可以”。)
答案2
您所看到的情况很可能是由于功能从内核网络堆栈卸载到网络接口和/或驱动程序。
网络接口仍会从网络接收单个数据包。但在数据包被交给内核之前,它们会被接口或驱动程序合并。
您可以使用此命令查看所有卸载功能的当前设置:
ethtool -k eth0
如果您想禁用此特定功能,可以使用以下命令:
ethtool -K eth0 generic-receive-offload off
您可以在以下位置阅读有关卸载的更多信息这个老问题。