我有一个客户端,每隔8秒就会向服务器发送一个数据包。如果服务器检测到数据包发送速度过快,则会断开客户端连接。在客户端我叫Sleep(8000);在发送数据包之前。在服务器端,我使用GetTickCount();计算数据包之间的时间。我希望这可以毫无问题地工作,但我一直在断开连接。
我使用WireShark来检查数据包时间,这就是我得到的: 包#时间 17 8.656064 72 16.957240 115 24.764741
24.764741 - 16.957240 = 7.807501< 8是我断线的原因。 我不明白这一点,因为在客户端我叫Sleep(8000);所以它应该每8秒或更长时间发送一次数据包。
第二个包是晚0.3秒,第三个包早约0.2。 有没有办法及时发送这些数据包?
答案 0 :(得分:2)
答案建议您不要太依赖时钟准确度并注意延迟来源是正确的。
然而,你出200毫秒的事实让我猜测你正在使用TCP并且你还没有关闭Nagle算法。对于时间敏感的协议,您应该将套接字设置为打开TCP_NODELAY。
所有其余的TCP延迟警告都适用;你真的不知道什么时候会发生,你需要在你的协议中处理它。
答案 1 :(得分:1)
问题实际上是一个古老的问题; TickCount会有所不同,即使在同一台计算机中的多个CPU之间也是如此:
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不可靠,通过网络发送数据包获得绝对精确是在消费级网络上实现的难点。
我的解决方案是,为了确保Sleep计时器等待的时间更长,然后Tick计时器不优雅,但足以让'fudge'解决问题。
您不能保证数据包会在X秒内到达,但可以确保在某段时间过后不会发送数据包。
答案 2 :(得分:1)
对我而言,你希望这会起作用似乎很奇怪。例如,尽管存在延迟,您的数据包可以被缓冲并通过线路一起发送。根据网络状况,它们可能无序到达或任意延迟。当它们在服务器端处理时,它们之间有多长时间是什么关系?服务器上的时间并没有说明客户端的时间。
答案 3 :(得分:0)
您不能指望网络上发送的个别数据包能够准确计时。而不是根据最后两个数据包之间的时间设置断开连接条件,而是在较长时间内对其进行平均 - 例如,如果在过去40秒内收到的数据包超过5个,则断开连接。