我需要一个TCP选项(ioctl),以立即发送数据。

7
我有一个不寻常的情况:我正在使用一个嵌入式Linux系统(英特尔盒子,目前使用2.6.20内核),它必须与一个具有部分破碎TCP实现的嵌入式系统通信。据我目前所知,他们希望我们每个消息都在单独的以太网帧中到达!当消息跨越以太网帧时,他们似乎会遇到问题。
我们与该设备在本地网络上,在我们之间没有路由器(只有交换机)。
当然,我们正试图强制他们修复他们的系统,但那可能不可行。
我已经在我的套接字上设置了TCP_NODELAY(我连接到它们),但这仅在我不尝试一次发送多个消息时才有用。如果我连续发送几条出站消息,这些消息往往会被放入一两个以太网帧中,这会对另一个系统造成麻烦。
我通常可以通过使用计时器避免发送消息过于接近来避免此问题,但这显然会限制我们的吞吐量。此外,如果我将时间降低得太低,我会冒着网络拥塞阻塞数据传输并最终允许多个消息进入同一个数据包的风险。
是否有一种方法可以告诉我驱动程序是否有数据排队?是否有一些方法可以强制驱动程序在独立的传输层数据包中发送独立的写入调用?我已经查看了socket(7)和tcp(7)手册,并没有找到任何内容。可能只是我不知道我在寻找什么。
显然,UDP将是一个出路,但同样,在这一点上我认为我们无法让另一端做出太多更改。
非常感谢任何帮助。
6个回答

11

如果我理解正确的话,设置TCP_NODELAY选项应该会刷新所有数据包(即tcp.c通过调用tcp_push_pending_frames实现设置NODELAY)。所以,如果您在每次发送调用后设置套接字选项,您应该能获得想要的结果。


如果你没有看到效果,请尝试在每次发送后将其设置为0,然后再设置为1。 - psq

2

除非您确定问题所在,否则无法解决问题。

如果他们犯了新手错误,假设recv()仅接收一个消息,那么我看不到完全解决它的方法。每个以太网帧只发送一个消息是一件事,但是如果在接收者调用recv()之前到达多个以太网帧,则仍将在一个调用中获取多个消息。

即使他们可以告诉您他们调用recv()的频率,网络拥塞也几乎不可能防止这种情况(同时保持良好的吞吐量)。


1
很不幸,据我所知,另一端的设备并没有运行正常的TCP协议栈。它是一个小型嵌入式设备,并且他们在某个时候添加了自己设计的以太网板。从行为上看,我怀疑他们在以太网帧中进行了一些操作。 - Michael Kohne

1

也许可以设置TCP_NODELAY并将MTU降低到每个帧中最多只有1个消息?哦,还要在发送数据包时添加“dont-fragment”标志。


好主意。不幸的是,由于消息大小不统一,我无法选择一个MTU来确保在这种情况下每个帧只有一个消息。 - Michael Kohne

0
你尝试过为每个消息打开一个新的套接字并立即关闭它吗?虽然开销可能会让人感到恶心,但这应该可以限定你的消息。

很遗憾,这将会在另一端引起比分段消息更多的麻烦,所以在这种情况下它是行不通的。 - Michael Kohne

0
在最糟糕的情况下,您可以进一步降低一个级别(原始套接字),在那里您可以更好地控制发送的数据包,但是您必须处理TCP的所有细节。

-1
也许你可以尝试将tcp堆栈设置为低延迟模式:
echo 1 > /proc/sys/net/ipv4/tcp_low_latency

应该尽快发出数据包而不是合并数据。请阅读tcp(7)的手册以获取更多信息。


根据 Linux 内核(net/ipv4/tcp.c)中的代码判断,tcp_low_latency 标志仅影响从 TCP 栈读取数据到应用程序缓冲区的过程。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接