Задержка Java TCP - PullRequest
       19

Задержка Java TCP

4 голосов
/ 15 марта 2012

Я занимаюсь разработкой приложения для Android, связывающегося с TCP-Java-сервером через соединение WLAN.Приложение для Android - это игра, в которой спрайты перемещаются по экрану.Всякий раз, когда спрайт перемещается, AndroidClient отправляет свои координаты Java-серверу, который затем отправляет данные другим клиентам (максимум 4 клиентам).Сервер обрабатывает каждого клиента в отдельном потоке, обновления данных отправляются каждые 20 мс, а каждый пакет состоит из 1-10 байтов.Я нахожусь в сети на 70 Мбит (с эффективностью около 15 Мбит на моем беспроводном устройстве).

У меня проблемы с нестабильным соединением, и задержка составляет около 50-500 мс.каждый 10-30 пакет.Я установил для tcpNoDelay значение true, которое остановило постоянную задержку 200 мс, хотя она все еще сильно отстает.Поскольку я новичок как в Android, так и в сетях, я не знаю, стоит ли ожидать этого или нет.Мне также интересно, подойдет ли UDP для моей программы, поскольку я заинтересован в быстрой отправке обновлений, а не в том, чтобы каждый пакет доставлялся правильно.

Буду признателен за любые указания относительно того, как избежать / обойти эту проблему задержки,Общие советы о том, как реализовать такую ​​архитектуру клиент-сервер, также будут приветствоваться.

Ответы [ 2 ]

2 голосов
/ 15 марта 2012

В беспроводной локальной сети вы иногда видите пропущенные пакеты, что приводит к повторной передаче пакетов после задержки. Если вы хотите контролировать задержку перед повторной передачей, вам почти наверняка придется использовать UDP.

0 голосов
/ 02 февраля 2016

Вы определенно хотите использовать UDP.Для игры вам все равно, если позиция спрайта будет неправильной в течение короткого времени.Так что в этом случае идеальным является UDP.

Кроме того, если у вас есть какой-либо контроль над кодом сервера, я бы не стал использовать отдельные потоки для клиентов.Потоки полезны, если вам нужно вызывать библиотеки, которые вы не можете контролировать и которые можете заблокировать (например, потому что они касаются файла или пытаются выполнить дополнительное сетевое взаимодействие).Но они дорогие.Они потребляют много ресурсов и, как таковые, на самом деле делают вещи на медленнее , чем могли бы быть.

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

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

...