2012-03-15 7 views
4

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

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

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

+2

UDP определенно звучит как лучший вариант. –

+0

для игры, вы, вероятно, захотите добавить некоторое предсказание (вероятно, вы видели эффект неправильного предсказания в некоторых играх). – ninjalj

+0

Захват сетевой активности с помощью wirehark или tcpdump и отправьте его здесь. – gudok

ответ

2

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

0

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

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

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

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