如何在POSIX函数send()中关闭TCP PSH标志?

8
我正在使用以太网向步进电机系统发送命令。这些命令可以让电机移动,或者响应驱动器状态,或者配置驱动器等等... 有时候步进电机系统会挂起,或者无法执行命令,制造商检查了我提供的所有内容后告诉我要关闭TCP层中的PSH标志。以下是Wireshark截图,显示了我的代码使用PSH标志的情况:

enter image description here

我正在使用运行在Ubuntu(16.04)上的C++11。
我的发送函数如下所示:
int sendStatusCode = send(socket , *&pointerToMessageAsCharArray , sizeOfMessage , 0);

我查看了该函数的说明文档,我理解最后一个参数(我设置为0)是一个标志。但我不明白需要插入哪个值才能关闭PSH标志而不改变其他任何内容(如果可能的话)。你能帮忙吗? 编辑 消息的大小非常小,例如: const char m_ME[5] = {m_HEADER_ONE, m_HEADER_TWO, m_M_HEX, m_E_HEX, m_FOOTER_HEX}; 发送时看起来像这样: enter image description here 我发送的最大消息是8个字符,相当于8字节。

编辑 我实现了这个答案(如何在Linux中禁用Nagle算法?),但在我看来,TCP_NODELAY并没有关闭PSH标志。我用于检查的代码:

int noDelayState = 1; // 0 means prefer bandwidth optimization over low latency

int tcpPushOptionOff = setsockopt(m_socketRight
    , IPPROTO_TCP
    , TCP_NODELAY
    ,(char *) &noDelayState
    , sizeof(int));

if (tcpPushOptionOff < 0) { /* do smth */ }

1
你是否在发送套接字上通过setsockopt()设置了TCP_NODELAY选项?如果是这样,你可以尝试不设置该选项。 - Jeremy Friesner
2
Wireshark的输出是否表明您正在向电机系统发送部分命令?如果不是,我不明白PSH标志如何会引起问题——如果电机系统收到完整的命令包,则PSH标志似乎无关紧要。在这种情况下,很有可能这只是制造商的责任推卸。如果电机系统不能处理不完整的数据包,那么它本来也不是很好。毕竟,TCP连接是 - Andrew Henle
1
@AndrewHenle同意--这个建议只是为了测试和收集信息。我并不是提议将其作为永久解决方案。 - Jeremy Friesner
1
@Mike哦,这是责备游戏,无论是否取消设置PSH标志,电机控制器都会表现出来。一个电机控制器应该如何处理传入的数据包?坐在上面等待另一个吗?PSH标志应该是无关紧要的。制造商的回答有点可疑。这只是纯粹的猜测,但我从你的Wireshark转储中猜测,控制器无法处理你发送给它的每毫秒2-3个数据包,而“关闭PSH标志!”是制造商试图降低数据包速率的尝试。 - Andrew Henle
3
制造商在误导你。无论设置或清除,PSH标志都没有实际效果。它的存在是因为最初的TCP设计者设想了与我们最终得到的相当不同的编程接口。TCP_NODELAY对PSH标志没有影响,但是也没有人说它会有影响。你应该确保它处于关闭状态。 - user207421
显示剩余8条评论
1个回答

2
使用标准的Linux TCP协议栈,您无法直接控制此项。 PSH标志是否被设置由发送缓冲区和堆栈中的副本控制。使用类似于嵌入式LWIP协议栈这样的东西,您会有更多的控制权。
然而,请尝试将setsockopt(SO_SNDBUF)设置为非常小的值,并查看是否有所改善。比您的数据包大小还要小,即几个字节。但是,缓冲区大小设置不起作用,因为操作系统强制执行最小大小大于帧大小。

你不能将它设置为几个字节。平台会强制执行最小值,在Linux中是几千字节。 - user207421
@kert 我真的很惊讶我无法对这个标志做任何事情。感谢您关闭了这个问题的大门。 - Mike

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