3

我正在通过网络发送许多大小为 50 字节的 TCP 数据包。后来我发现 TCP 将几个 50 字节的数据包聚合成一个 TCP 数据包。我的问题是,有没有办法避免“C”程序中的 TCP 聚合?

4

4 回答 4

4

使用称为Nagle 算法的算法处理将多个发送的数据包打包成单个 TCP 数据包。要禁用它,请在您的套接字上设置TCP_NODELAY选项:

int flag = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));

请注意,这会降低您的网络效率,除非您确实需要立即发送每个数据包,否则应避免这样做。

于 2013-01-09T06:16:17.723 回答
3

TCP 从根本上不提供应用层的基于数据包的服务。使用 TCP 的应用程序不仅需要纯流,还必须提供自己的帧机制。

虽然该TCP_NODELAY选项通常会导致每个应用程序级别的写入都在单独的帧中进行(除非它大于 MTU),但不能保证。特别是,如果接收窗口已减小到零(在发送批量数据的连接上很常见),那么当接收窗口再次打开时,仍然可以合并多个写入。

此外,即使发送 TCP 没有合并您的写入,也无法阻止接收方在从套接字读取的一个应用程序级读取中呈现来自多个 TCP 帧的数据 - 当您的接收应用程序未连接时尤其会发生这种情况计划了一段时间,或者当连接上发生数据包丢失时。

如果您的应用程序假设发送端的每个应用程序级别的写入都将与接收端的应用程序级别的读取完全配对,那么您将自己设置为罕见且难以重现的错误。

于 2013-01-09T06:37:55.203 回答
1

根据定义,TCP 不提供任何打包服务。TCP 是一种面向字节流的协议。您能做的最好的事情就是将您自己的框架标记插入到您的数据中。然后,如果您的接收器至少可以检测到坏帧(可能是聚合数据)并丢弃此类数据,那么您就可以到达您想要的位置。

尽可能快地发送方法(ala NODELAY)不能保证有效,因为您的接收器仍然可以聚合数据。如果任何 tcp 数据由于某种原因被延迟,则更有可能发生这种情况

于 2013-01-12T01:59:28.140 回答
0

一种方法是在发送调用中使用 TCP_NODELAY 标志。但是,这取决于 TCP 堆栈是否支持。

于 2013-01-09T06:15:33.970 回答