我有一个客户端,它每隔8秒就会向服务器发送一个数据包。如果服务器检测到数据包发送过快,它将断开与客户端的连接。在客户端中,我在发送数据包之前调用了睡眠(8000);。在服务器端,我使用GetTickCount();来计算数据包之间的时间。我希望它能正常工作,没有任何问题,但我总是断线。
我使用WireShark检查数据包时间,得到的结果如下: Packet#时间17 8.656064 72 16.957240 115 24.764741
24.764741 - 16.957240 = 7.807501 <8是我断开连接的原因。我不理解这一点,因为在客户端中我调用了睡眠(8000);所以它应该每隔8秒或更长时间发送一次数据包。
第二个数据包延迟0.3秒,第三个数据包提前约0.2秒。有没有办法及时发送这些数据包?
发布于 2011-08-22 05:49:37
这个问题实际上是一个古老的问题;即使在同一台计算机中的多个CPU之间,TickCount也是不同的:
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/22c68353-1dbb-4718-a8d2-0679fdc0c298/
我的建议是将你的睡眠设置为高于8000,比方说9500,并且保持tickCount相同的机制,因此睡眠应该总是更高。
另一个要阅读的链接在这里:
http://en.wikipedia.org/wiki/Latency_(engineering)#Computer_hardware_and_operating_system_latency
具体参考Microsoft Windows上的段落。
更新:
我不确定为什么这会被否决,但请允许我在这里澄清一下我所看到的问题。
不能依赖TickCount作为时间的特定度量,除非它被本地化到一个处理单元。第一个到MSDN的链接提供了关于原因的引用。
其次,Windows本身的定时器逻辑可能有不准确之处。
最后,就其本身而言,您的基于晶体的定时器可能会有所不同,因为众所周知,大气条件会影响压电振荡。
http://en.wikipedia.org/wiki/Crystal_oscillator#Temperature_effects
总而言之,TickCount并不可靠,而且在消费级网络上很难实现在网络上发送数据包的绝对精确度。
我的解决方案是,确保睡眠计时器比滴答计时器等待的时间更长,这并不优雅,但足够的“软化”来解决这个问题。
您不能保证数据包将在X秒内到达,但您可以非常确定它不会在经过特定持续时间之前发送。
发布于 2011-08-22 10:11:12
建议您不要太依赖时钟精度并了解延迟来源的答案是正确的。
然而,您在200ms之前就离开了,这一事实让我猜测您正在使用TCP,并且您没有关闭Nagle算法。对于时间敏感的协议,您应该将套接字设置为打开TCP_NODELAY。
所有其余的TCP延迟警告都适用;您并不真正知道什么时候会发生事情,您需要在您的协议中处理它。
发布于 2011-08-22 05:55:47
对我来说,这似乎很奇怪,你会期望这能起作用。例如,您的数据包可以被缓冲并一起通过线路发送,尽管存在延迟。根据网络条件,它们可能会乱序到达或具有任意延迟。当它们在服务器端处理时,它们之间有多长时间又有什么关系呢?服务器上的计时与客户端上的计时没有任何关系。
https://stackoverflow.com/questions/7141382
复制相似问题