Проблема синхронизации пакетов - PullRequest
1 голос
/ 22 августа 2011

У меня есть клиент, который каждые 8 ​​секунд отправляет пакет на сервер. Если сервер обнаружит, что пакеты отправлены слишком быстро, он отключит клиента. В клиенте я звоню Sleep (8000); перед отправкой пакета. На стороне сервера я использую GetTickCount (); рассчитать время между пакетами. Я ожидал, что это сработает без проблем, но я продолжаю отключаться.

Я использовал WireShark для проверки времени пакетов, и вот что я получил: Пакет № Время 17 8,656064 72 16,957240 115 24,764741

24.764741 - 16.957240 = 7.807501 <8 - причина, по которой меня отключили. Я не понимаю этого, потому что в клиенте я звоню Sleep (8000); поэтому он должен отправлять пакеты каждые 8 ​​секунд или более. </p>

2-й пакет опаздывает на 0,3 секунды, а 3-й - рано, примерно на 0,2. Есть ли способ отправить эти пакеты вовремя?

Ответы [ 4 ]

2 голосов
/ 22 августа 2011

Ответы, советующие вам не слишком полагаться на точность часов и знать источники задержки, верны.

Однако тот факт, что вы вышли на 200 мс, заставляет меня догадываться, что вы используете TCP, и вы не выключили алгоритм Nagle. Для протокола, чувствительного ко времени, вы должны установить в своем сокете значение TCP_NODELAY.

Применяются все остальные предупреждения о задержке TCP; вы на самом деле не знаете, когда что-то произойдет, и вам нужно учесть это в своем протоколе.

1 голос
/ 22 августа 2011

Мне кажется странным, что вы ожидаете, что это сработает. Например, ваши пакеты, возможно, могут быть буферизованы и отправлены по сети вместе, несмотря на задержку В зависимости от состояния сети они могут прийти не в порядке или с произвольными задержками. Какое значение имеет сколько времени между ними, когда они обрабатываются на стороне сервера? Время на сервере ничего не говорит о времени на клиенте.

1 голос
/ 22 августа 2011

Проблема на самом деле старая;TickCount варьируется, даже между несколькими процессорами на одном компьютере:

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

Я предлагаю установить для вашего Sleep значение выше 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 секунд, но вы можете убедиться, что он не будет отправлен до истечения определенной продолжительности.

0 голосов
/ 23 августа 2011

Вы не можете ожидать, что отдельные пакеты, отправленные по сети, будут точно синхронизированы. Вместо установки условия отключения на основе времени между двумя последними пакетами, усредните его в течение более длительного периода - например, отключите, если за последние 40 секунд было получено более 5 пакетов.

...