1

我有一个客户端,每 8 秒将向服务器发送一个数据包。如果服务器检测到数据包发送速度过快,它将断开客户端。在客户端我调用 Sleep(8000); 在发送数据包之前。在服务器端,我使用 GetTickCount(); 计算数据包之间的时间。我希望这可以正常工作,但我一直断开连接。

我使用 WireShark 检查数据包时间,这就是我得到的:Packet# Time 17 8.656064 72 16.957240 115 24.764741

24.764741 - 16.957240 = 7.807501 < 8 是我断开连接的原因。我不明白这一点,因为在客户端我调用 Sleep(8000); 所以它应该每 8 秒或更长时间发送一次数据包。

第二个数据包晚了 0.3 秒,第三个数据包早了大约 0.2 秒。有没有办法及时发送这些数据包?

4

4 回答 4

2

建议您不要过分依赖时钟精度并注意延迟来源的答案是正确的。

但是,您退出 200 毫秒的事实使我推测您正在使用 TCP,并且您没有关闭 Nagle 算法。对于时间敏感的协议,您应该将您的套接字设置为启用 TCP_NODELAY。

所有其余的 TCP 延迟警告都适用;你真的不知道事情什么时候会发生,你需要在你的协议中处理它。

于 2011-08-22T02:11:11.923 回答
1

这个问题实际上是一个古老的问题。TickCount 会有所不同,即使在同一台计算机的多个 CPU 之间也是如此:

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/22c68353-1dbb-4718-a8d2-0679fdc0c298/

我的建议是将你的 Sleep 设置为高于 8000,比如 9500,并为 tickCount 保持相同的机制,因此 Sleep 应该总是更高。

另一个阅读链接在这里:

http://en.wikipedia.org/wiki/Latency_(engineering)#Computer_hardware_and_operating_system_latency

具体参考 Microsoft Windows 上的段落。

更新:

我不确定为什么这会被否决,但请允许我在这里澄清问题,正如我所看到的那样。

TickCount 不能作为一种特定的时间度量来依赖,除非它被本地化到一个处理单元。MSDN 的第一个链接提供了有关原因的引用。

其次,Windows 本身的计时器逻辑可能存在不准确之处。

最后,就其本身而言,基于 Crystal 的计时器可能会有所不同,因为众所周知,大气条件会影响压电振荡。

http://en.wikipedia.org/wiki/Crystal_oscillator#Temperature_effects

总而言之,TickCount 不可靠,在网络上发送数据包时获得绝对精度在消费级网络上很难实现。

我的解决方案是确保 Sleep 计时器等待的时间比 Tick 计时器更长,这并不优雅,但足以解决问题。

您不能保证一个数据包会在 X 秒内到达,但您可以非常确定它不会在某个持续时间过去之前发送。

于 2011-08-21T21:49:36.680 回答
1

对我来说,您期望这会起作用似乎很奇怪。例如,尽管有延迟,您的数据包可能会被缓冲并通过网络一起发送。根据网络状况,它们可能会出现乱序或任意延迟。当它们在服务器端处理时,它们之间有多少时间有什么关系?服务器上的时间并没有说明客户端上的时间。

于 2011-08-21T21:55:46.740 回答
0

您不能期望在网络上发送的单个数据包的时间会如此精确。不要根据最后两个数据包之间的时间来设置断开连接条件,而是在更长的时间内对其进行平均 - 例如,如果在过去 40 秒内收到超过 5 个数据包,则断开连接。

于 2011-08-23T04:56:11.333 回答