DatagramSocket случайным образом прекращает прием DatagramPackets - PullRequest
0 голосов
/ 21 апреля 2019

Я создаю многопользовательскую java-игру, которая разрешает постоянную отправку DatagramPackets между клиентом и сервером по локальной сети.

Случайным образом клиент DatagramSocket прекращает прием пакетов с сервера и, следовательно, клиент не получаетобновления с сервера.

Похоже, что DatagramSocket полностью прекращает прием и не возобновляет прием.Эта проблема возникала в каждой клиент-серверной ситуации.

Если у кого-то есть какие-либо идеи, скажите, как я из идей!

Windows PC, Java 1.8

listening = true
PACKET_SIZE = 3096
buffer = new byte[PACKET_SIZE]
addr = InetAddress.getLocalHost()
port = new Random().nextInt(65536);
processor = Object

while(listening) {
    DatagramPacket p = new DatagramPacket(buffer, buffer.length, addr, port);

    try {
        socket.receive(p); // Code stops here
        processor.add(p);  // sends to queue to be processed

    } catch(IOException e) {
        e.printStackTrace();
    }

    buffer = new byte[PACKET_SIZE];

}

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

Ответы [ 2 ]

2 голосов
/ 21 апреля 2019

Краткий ответ: либо удаленный сервер прекратил отправлять дейтаграммы UDP, либо сеть по какой-то причине перестала их доставлять.


Я предполагаю, что у вас есть какой-то способ сообщить серверу случайный порти IP, который вы используете для прослушивания дейтаграмм.Если сервер не использует тот же порт и IP для отправки, UDP-датаграммы будут молча исчезать.(Но вы говорите, что ваш клиентский код работает некоторое время, а затем останавливается. Это означает, что IP и порт верны.)

Я также предполагаю, что вы бы сообщили нам, если выполучаю исключения и вижу следы стека (!)

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

  1. Сервер прекратил отправку.

    • Возможно, он разбился.
    • Возможно, он "случайно" переключился на другой порт.
    • Возможно, он заблокирован, потому что ожидает чего-то, что не произойдет.Например, прибытие ответного сообщения, которое было потеряно.
  2. Сеть прекратила передачу пакетов UDP.Трудно понять, почему:

    • Это может быть связано с какой-то защитой от DOS, реализованной в некотором брандмауэре.
    • Если ваш клиент находится за шлюзом NAT, и вы используете «дырокол» для пропуска UDP-пакетов, возможно, «дыра» истекла.(Но вы говорите, что это в локальной сети, что подразумевает, что NAT не должен быть задействован. NAT для используемой трансляции IP-адресов на логической границе между двумя сетями; например, частная сеть <-> общедоступный Интернет.)

Как предложено, попробуйте использовать Wireshark с обоих концов, чтобы увидеть, отправляются ли серверные пакеты UDP и продолжают ли они поступать на клиент.Это поможет вам сузить проблему.

Обратите внимание, что если вы пытаетесь реализовать двухстороннюю или многоканальную связь по UDP, вам нужно разрешить случайное удаление сообщений.Протоколы уровня приложения (реализованные с использованием транспорта UDP) должны иметь возможность обнаруживать 1 и восстанавливаться после этого во всех сценариях, в которых сообщение может быть отброшено.Если вы поймете это неправильно, одна из возможностей будет состоять в том, что протокол «блокируется».


1 - Это обычно включает реализацию тайм-аутов на некотором уровне.Однако просто установка времени ожидания на receive (как предполагает другой ответ) не не решает проблему.

0 голосов
/ 21 апреля 2019

Некоторые предложения по отладке:

  • Установите разумное время ожидания для сокета с помощью setSoTimeout (int milliseconds), а также перехватите SocketTimeoutException.Сервер, возможно, отправил пакет, и по какой-то причине он так и не пришел.Если сервер ожидает ответа перед отправкой другого пакета, ваш клиент будет ждать бесконечно долго.Затем вы можете перехватить SocketTimeoutException и отправить / отправить соответствующий пакет на сервер.

  • Установить Wireshark для мониторинга пакетов, отправленных с сервера, а также пакетов, полученных клиентом.Вы должны быть в состоянии увидеть, действительно ли пакет отправляется сервером, пакет никогда не принимается клиентом или пакет фактически принимается клиентом, но что-то идет не так на стороне клиента.

...