我使用的是 Linksys WRT 1900 ACS 路由器,搭载 OpenWrt 15.05.1。我在其上运行一个 C 程序,该程序会定期(16 毫秒)发送某些 WiFi UDP 多播数据包,然后在标准输出上打印系统时间。我可以清楚地看到接收端的异常,但它们不会显示在打印的时间值中。
这让我相信,即使在 sendto() 系统调用返回后,也会发生某种程度的缓冲/等待。我如何才能获得数据包实际发出的时间?
注意:该多播网络上的所有接收器的异常情况都是相同的,因此问题不在于接收器端。
答案1
不幸的是,你不能。
总结
sendto
一旦数据包被发送到 IP 堆栈,该函数就会返回。内核 IP 堆栈将处理该数据包,并尝试通过您的 WiFi 接口发送该数据包。
问题就在这里,WiFi 传输延迟很长(与有线以太网相比)且不规律。以下是您应该预期的延迟示例:
此对数图显示了我的服务器与路由器之间以及我的服务器与无线客户端之间的 ping 时间延迟。由于ping
是双向的,单向延迟可能约为其一半。
有线通信显示 ping 时间约为 300us,而无线链路显示平均 7ms(延迟 23 倍)。
现在几乎是相同的图表,这次是线性的,以突出不规则性:
Wifi ping 时间在 6 到 45 毫秒之间变化。
解决方案?
由于sendto
函数返回的时间比您预期的要早,因此您无法真正测量数据包的发送时间。如果您真的对数据包的发送时间感兴趣,您可以通过等待客户端的响应并将往返时间减半来估计它。
但,正如你已经知道的那样,由于这是多播,因此所有 WiFi 客户端都会同时接收数据包。
因此,真正的问题是:你想实现什么?
例如,如果你想让所有客户端同时播放相同的音频流,那么某种软件锁相环应该可以解决问题。
如果您想尽量减少延迟,您仍然可以尝试微调您的 WiFi 设置,特别是路由器和客户端上的省电设置。
如果你想实现一些目标硬实时性能,您可能应该忘记 WiFi。