Как получить задержку между сервером и клиентом на C#?

Я работаю над серверным приложением C# для игрового движка, который я пишу в ActionScript 3. Я использую авторитетную модель сервера, чтобы предотвратить обман и обеспечить честную игру. Пока все работает хорошо:

когда клиент начинает двигаться, он сообщает серверу и начинает рендеринг локально; сервер затем сообщает всем остальным, что клиент X начал двигаться, среди деталей, чтобы они также могли начать рендеринг. Когда клиент перестает двигаться, он сообщает серверу, что выполняет вычисления на основе времени, когда клиент начал двигаться, и клиент отображает задержку тика и отвечает всем, чтобы они могли обновляться с правильными значениями.

дело в том, что когда я использую задержку тика по умолчанию 20ms на вычислениях сервера, когда клиент перемещается на довольно большое расстояние, есть заметный наклон вперед, когда он останавливается. Если я немного увеличу задержку до 22ms, в моей локальной сети все работает очень гладко, но в других местах наклон по-прежнему там. Немного поэкспериментировав, я заметил, что дополнительная задержка в значительной степени связана с задержкой между клиентом и сервером. Я даже свел его к формуле, которая будет работать довольно хорошо: delay = 20 + (latency / 10).

Итак, как я могу получить задержку между определенным клиентом и сервером (я использую асинхронные сокеты). Усилие процессора не может быть слишком большим, так как сервер не работает медленно. Кроме того, это действительно лучший способ, или есть больше эффективный/простой способ сделать это?

5 ответов


Извините, что это не прямой ответ на ваш вопрос, но, вообще говоря, вы не должны слишком сильно полагаться на измерение задержки, потому что она может быть довольно переменной. Мало того, вы не знаете, является ли время пинга, которое вы измеряете, даже симметричным, что важно. Нет смысла применять 10 мс коррекции задержки, если окажется, что время пинга 20 МС на самом деле 19 мс от сервера к клиенту и 1 мс от клиента к серверу. И задержка в терминах приложения не такая же, как в сетевые условия-вы можете пинговать определенную машину и получить ответ в 20 мс, но если вы связываетесь с сервером на этой машине, который обрабатывает только сетевой ввод 50 раз в секунду, то ваши ответы будут отложены на дополнительный 0 до 20 мс, и это будет меняться довольно непредсказуемо.

Это не значит, что измерение задержки не имеет места в сглаживании прогнозов, но это не решит вашу проблему, просто очистите ее немного.

на лицо проблема здесь, похоже, в том, что вы отправляете информацию в первом сообщении, которое вы используете для экстраполяции данных до получения последнего сообщения. Если все остальное остается постоянным, то вектор движения, заданный в первом сообщении, умноженный на время между сообщениями, даст серверу правильное конечное положение, в котором клиент был примерно сейчас-(latency/2). Но если задержка вообще изменится, время между сообщениями будет расти или сокращаться. Клиент может знать, что он переместил 10 единиц, но сервер имитировал его перемещение 9 или 11 единиц, прежде чем ему сказали привязать его к 10 единицам.

общее решение этого - не предполагать, что задержка останется постоянной, а отправлять периодические обновления позиции, которые позволяют серверу проверять и исправлять позицию клиента. Всего 2 сообщения как у вас сейчас, все ошибки найдены и исправлены после 2-го сообщения. С большим количеством сообщений ошибка распространяется на многие другие точки выборки, позволяющие более плавная и менее заметная коррекция.

Это никогда не может быть идеальным, хотя: все, что требуется, это всплеск отставания в последнюю миллисекунду движения, и представление сервера будет превышено. Вы не можете обойти это, если вы предсказываете будущее движение на основе прошлых событий, так как нет реальной альтернативы выбору правильного, но поздно или неправильно, но своевременно, поскольку информация требует времени для путешествия. (Виноват Эйнштейн.)


одна вещь, чтобы иметь в виду при использовании ICMP на основе пинг это сетевое оборудование часто дает ICMP-трафику более низкий приоритет, чем нормальный пакеты, особенно когда пакеты пересекают сетевые границы, такие как WAN-ссылки. Это может привести к падению пингов или показать более высокую задержку, чем трафик фактически испытывает и поддается быть индикатором проблем, а не инструментом измерения.

расширение использования из качество услуг (QoS) в сетях только усугубляет это, и как следствие, хотя ping по-прежнему остается полезным инструментом, необходимо понимать, что это может не быть истинным отражением задержки сети для не-ICMP на основе реальные трафик.

есть хороший пост в блоге Itrinegy как вы измеряете задержку (RTT) в сети в эти дни? об этом.


вы можете использовать уже имеющиеся Ping класса. Должно быть предпочтительнее, чем писать свой собственный ИМХО.


есть команда" ping", где вы отправляете сообщение с сервера клиенту, а затем время, необходимое для получения ответа. За исключением сценариев перегрузки процессора, он должен быть довольно надежным. Чтобы получить время в одну сторону, просто разделите время на 2.


мы можем измерить туда и обратно времени С помощью Ping класс .NET Framework.

создать экземпляр a Ping и подписаться на PingCompleted событие:

Ping pingSender = new Ping();
pingSender.PingCompleted += PingCompletedCallback;

добавить код для настройки и действия ping.

наши PingCompleted обработчик событий (PingCompletedEventHandler), имеет PingCompletedEventArgs