【发布时间】:2018-07-04 04:15:31
【问题描述】:
我在 Windows 7 中编写了一个服务器 python 脚本,用于将以太网 UDP 数据包发送到运行 C 客户端接收程序的 UNIX 系统,该程序将消息发送回服务器。但是,有时(并非总是)python 发送到的最后一个端口(并且始终是最后一个端口)中的消息要等到下一批 4 条消息被发送后才会到达。这会导致接收到最后一个端口的消息的时间与发送时不正确,并且我不能在同一个端口上背靠背发送两条消息。
我已经能够在Wireshark 中验证这一点,方法是查找大约同时到达的两条消息,因为未收到的一条已与另一条一起处理。我还在recv() 函数之后检查了时间,它显示了一个很长的延迟,然后是一个很短的延迟,因为它基本上收到了两个数据包。
我已尝试解决此问题,但有助于我解释问题或如何解决问题:我可以在每个 sendto() 之间添加延迟,我将成功发送和以正确的时间接收所有消息,但我希望测试按照我在下面编写的方式进行;我增加了接收线程的优先级,认为我的以太网接收没有收到信号来接收包或者某些过程花费了太长时间,但这没有用,20ms 应该比处理所需的时间多得多数据;我删除了端口 C 和 D,然后端口 B 丢失消息(只有一个端口不会引起问题),我认为减少端口数量会改善时序;在 PORTD 之后立即发送到虚拟 PORTE 可以让我以正确的时间接收所有消息(我假设问题已转移到 PORTE);我还在 UNIX 环境和 C 代码中重现了 python 脚本,并且遇到了同样的问题,指出了接收问题;我还将我的 recv 函数设置为每 1ms 超时一次,希望它能够以某种方式恢复,即使时间会有点偏离,但我仍然看到背靠背的消息。我还检查了是否没有丢弃任何 UDP 数据包,并且缓冲区是否足够大以容纳这 4 条消息。任何新想法都会有所帮助。
这是代码的核心,python脚本会发送4个数据包。一条 20 字节的消息发送到 C 中相应的等待线程并延迟 20ms
python 代码的表示形式类似于
msg_cnt = 5000
while cnt < msg_cnt:
UDPsocket.sendto(data, (IP, PORTA))
UDPsocket.sendto(data, (IP, PORTB))
UDPsocket.sendto(data, (IP, PORTC))
UDPsocket.sendto(data, (IP, PORTD))
time.sleep(.02)
cnt++
C 代码有 4 个线程在其相应端口上等待接收。本质上,每个线程都应该接收其数据包,对其进行处理,然后将其发送回服务器。在下一组消息到达之前,这个过程应该不到 20 毫秒
void * receiveEthernetThread(){
uint8_t ethRxBuff[1024];
if((byteCnt = recv(socketForPort, ethRxBuff, 1024, 0)) < 0){
perror("recv")
}else{
//Process Data, cannot have back to back messages on the same port
//Send back to the server
}
}
【问题讨论】:
-
所以如果我没看错的话,你在wireshark上看到的是来自Python的消息总是间隔适当的。这是真的吗?
-
就发送而言,是的。 Wireshark 将显示 4 条消息突发之间的纳秒延迟,然后完美显示 20ms 延迟。但是,在接收过程中,有时来自最后一个端口的消息似乎是背靠背的。在 recv() 之后立即测试时间表明,假设我发送一组四个,然后发送另一个。如果第一组错过了最后一个端口,我会看到一个很大的延迟(大约 40 毫秒显示下一条消息),因为它最后一次进入该线程,然后是一个快速延迟,这意味着它基本上进入了两次线程。
-
UDP 不保证数据包的顺序,甚至不保证所有数据包都已交付。如果您需要这些属性,您需要自己构建它们,使用在 UDP 之上提供它们的库(例如,QUIC),或者使用不同的协议(例如,TCP)。至于时间问题,可能会有一些缓冲(参见en.wikipedia.org/wiki/Bufferbloat)。
-
谢谢!我将研究缓冲膨胀,似乎它可能是问题的一部分,听起来与我对该问题的初步结论相似。速度和时间肯定有关系。不幸的是,我被 UDP 困住了。我也尝试了长达 1 秒的延迟,但仍然遇到同样的问题。
-
你能检查下处理器亲和性对接收端的影响吗?这将是 taskset 命令,基本上将服务器进程固定到特定的 cpu/core。以下是可能相关的手册页的摘录:出于性能原因,调度程序尝试将进程保持在同一个 CPU 上,只要可行。因此,强制使用特定的 CPU 亲和性仅在某些应用程序中有用。
标签: python c linux multithreading sockets