在不同的TCP段中发送数据,不会被TCP栈合并

Send data in separate TCP segments without being merged by the TCP stack

本文关键字:TCP 合并 段中发 数据      更新时间:2023-10-16

Linux (Kernel 3.0.0.12;我想通过(POSIX) send-call发送一些tcp数据包。

使用Wireshark,我可以看到数据包不是在单独的tcp帧中发送的,而是两个或多个数据包一起发送的。

有没有办法告诉系统在自己的tcp数据包中从一个send()缓冲区发送数据?程序流不应该在send-call处阻塞。

您的TCP堆栈正在实现Nagle算法,试图通过缓冲数据来提高效率。这是一种常见的优化,其目的是摊销40+字节(TCP + IP)报头的成本。堆栈不是发送多个小数据包,而是缓冲数据并将它们组合成一个更大的数据包,从而减少了报头开销。

TCP栈不是无限缓冲的。只要连接上有一些未确认的已发送数据,发送方就会继续缓冲。下一个包在:

  • 一个完整的数据包值可以发送
  • 所有先前发送的数据被接收方确认

您通常可以通过设置TCP_NODELAY套接字选项来禁用此功能。

setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));

如果您希望每个数据包单独发送,请考虑使用UDP。但是,您必须实现自己的错误检测和重传丢失的数据包等…

您可以关闭Nagle,但最好停止与TCP堆栈的战斗。最好在你的协议中添加某种形式的帧,这样你就不需要担心你的传输单元是否被聚合和/或分割了。

在发送者中,这通常意味着使用终止字符或给出长度。

在接收端,它意味着知道如何读到一些终止字符,和/或知道如何使用接收到的传输单元的一部分,或从多个传输单元组装一个完整的消息。

我喜欢用buffsock来做这个,尽管它是Python的一项技术。但是你可能想要c++类似的东西:http://stromberg.dnsalias.org/strombrg/bufsock.html

"packet"。

不,这就是拥有一个"网络堆栈"的全部意义——你的以太网帧可以独立于更高级别的TCP/IP堆栈进行传输和路由。你绝对不想插手这件事!