2015-01-12 4 views
0

게임 서버 정보를 읽는 Java 응용 프로그램을 작성하고 있습니다. 그게 전부이며, 같은 일을하는 루프에서 돌아갑니다.Java DatagramSocket은 몇 번의 실행 후 SocketTimeoutException을 throw합니다.

문제는 처음에 잘 작동한다는 것입니다. 응답이 있습니다. 일부 (상수가 아닌) 시간이 지나면 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있어서, 상기 프로토콜을 설명한다 here

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; 
} 

.

다른 게임의 경우 동일한 문제가 있지만 현재 SAMP에 대한 조사는 프로토콜이 가장 단순한 것으로 보입니다.

응용 프로그램이 Linux, Debian 7.0에서 실행됩니다. 방화벽을 완전히 비활성화하려고했습니다.

+1

getSocket() 메서드는 이전에 만들어진 소켓을 반환합니까, 아니면 지속적으로 새로운 소켓을 생성합니까? – ControlAltDel

+0

항상 동일한 소켓을 반환합니다. 나는 생성자에서 소켓을 생성하고'getSocket()'이 그것을 반환한다. – Bebras

답변

0

그래서 답장이 없어 졌거나 보내지지 않았습니다. 둘 중 하나에 대처해야합니다. UDP는 신뢰할 수없는 프로토콜이며 코드에 버그 나 예기치 않은 종료가 포함되어 있습니다.

NB 수신 할 주소와 포트를 초기화하는 데는 아무런 의미가 없습니다. DatagramPacket 들어오는 패킷의 원본 주소 : 포트로 덮어 쓰게됩니다.

+0

패킷 손실에 대해 알고 있습니다. 하지만 현재 서버가 시간을 초과하면 5 번 더 시도하고이 시간에는 소켓 시간 제한이 있습니다 (이 모든 것은 시간이 지나면 발생합니다). 패킷 손실이 그렇게 높을 수 있습니까? 팁을 주셔서 감사합니다. – Bebras

+0

응답 패킷이 손실되면 손실됩니다. 다시 시도해도 마술처럼 다시 나타나지 않습니다. 다시 시도해야하는 것은 전체 요청/응답주기이며 요청이 모두 멱등한지 확인하는 것입니다. – EJP

+0

그것이 내가 의미했던 것입니다. 나는 요청을 보내고 그것을받는 것을 시도한다. 나는 이것을 최대 5 번 시도한다. – Bebras

관련 문제