2015-01-12 2 views
0

Я пишу приложение Java, которое читает информацию о игровом сервере. Это все, что он делает, он работает в цикле, делая то же самое.Java DatagramSocket вызывает исключение SocketTimeoutException после нескольких прогонов

Проблема в том, что сначала она отлично работает, я получаю ответ. После некоторого (не постоянного числа) раз он начинает бросать исключение SocketTimeoutException.

Это метод, который я использую для запроса сервера SAMP.

private ByteBuffer sendQuery(char opcode) throws IOException { 

    ByteBuffer bf = ByteBuffer.allocate(11); 
    bf.order(ByteOrder.LITTLE_ENDIAN); 
    bf.put("SAMP".getBytes("US-ASCII")); 
    bf.put(encodeIP(getIp())); 
    bf.putShort((short)getPort()); 
    bf.put((byte)opcode); 
    Logger.getLogger().log("Request to " + this.getAddress().getHostString() + ":"+ByteConvert.bytesToHexString(bf.array())); 

    DatagramPacket packet = new DatagramPacket(bf.array(), bf.capacity(), getAddress().getAddress(), getPort()); 
    getSocket().send(packet); 

    byte[] buffer = new byte[4096]; 
    packet = new DatagramPacket(buffer, buffer.length, getAddress().getAddress(), getPort()); 
    getSocket().receive(packet); 
    if(packet.getLength() > 4096) 
     Logger.getLogger().log("Large packet received from " + this.getIp() + " :"+packet.getLength()); 
    bf = ByteBuffer.allocate(packet.getLength()); 
    bf.order(ByteOrder.LITTLE_ENDIAN); 
    bf.put(buffer, 0, packet.getLength()); 
    bf.flip(); 
    return bf; 
} 

encodeIP метод:

private static byte[] encodeIP(String s) throws IOException { 
    String[] ip = s.split("\\."); 
    byte[] bytes = new byte[ip.length]; 
    for(int i = 0; i < ip.length; i++) { 
     bytes[i] = (byte)Integer.parseInt(ip[i]); 
    } 
    return bytes; 
} 

Протокол документально here.

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

Приложение работает на Linux, Debian 7.0. Я попытался полностью отключить брандмауэр.

+1

Ваш метод getSocket() возвращает ранее созданный сокет, или он постоянно создает новый? – ControlAltDel

+0

Он всегда возвращает тот же разъем. Я создаю сокет в используемом конструкторе и 'getSocket()' возвращает его. – Bebras

ответ

0

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

NB нет смысла инициализировать адрес и порт DatagramPacket, который вы собираетесь получить. Они будут перезаписаны адресом источника: порт входящего пакета.

+0

Я знаю об потери пакетов. Но в настоящее время, если сервер истекает, я пробую его еще 5 раз, и все эти времена есть тайм-аут сокета (все это происходит только через некоторое время). Может ли потеря пакетов высока? И спасибо за подсказку :) – Bebras

+0

Если пакет ответа потерян, он потерян. Повторная попытка не заставит ее волшебно появиться. То, что вы должны повторить, - это весь цикл запроса/ответа, гарантирующий, что ваши запросы, конечно, идемпотентны. – EJP

+0

Вот что я имел в виду. Я пытаюсь отправить запрос, а затем получить его. Я пробую это до 5 раз. – Bebras

Смежные вопросы