2014-03-13 3 views
1

클라이언트 재시작 또는 종료를 수행하는 동안 모든 소켓 연결은 서버 측의 CLOSE_WAIT에 정지합니다. XdrAble은 직렬화 된 데이터를 XDR 스트림으로 보내는 데 사용됩니다. 풀은 표준 KeyedSocketPool의 객체입니다. MAXIMUM_RETRY, MAXIMUM_RETYR_BEFORE_RESET_POOL은 풀 연결을 재설정하기 위해 정의 된 상수입니다. 연결을 닫는 동안 내가 누락되었습니다.Java 서버 소켓 클라이언트 종료 또는 클라이언트 재시작 중 TCP 연결이 CLOSE_WAIT 상태로 고정됨

공개 RESP 호출 (REQ 요청 RESP 응답의 INT requestLength, INT 시간 초과)는 예외 {
소켓 socket = NULL을 발생; 연결을 닫는 동안

IOException ioException = null; 

short attempts = 0; 
boolean needResetPool = false; 

while (true) 
{ 
    ioException = null; 

    try 
    { 
    // Get socket (open if not connected) 
    socket = (Socket) pool.borrowObject(); 
    socket.setSoTimeout (timeOut); 

    // Send request 
    BufferedOutputStream outputStream = new BufferedOutputStream (socket 
     .getOutputStream()); 
    XdrBufferEncodingStream xdrIn = new XdrBufferEncodingStream (
     requestLength); 
    xdrIn.beginEncoding (socket.getInetAddress(), socket.getPort()); 
    request.xdrEncode (xdrIn); 
    xdrIn.endEncoding(); 
    outputStream.write (xdrIn.getXdrData()); 
    outputStream.flush(); 
    xdrIn.close(); 

    // Read response 
    BufferedInputStream inputStream = new BufferedInputStream (socket 
     .getInputStream()); 
    byte[] buffer = new byte[UreMsgBodyLength.MAXIMUM_MSG_LEN]; 
    int bytesRead = inputStream.read (buffer); 

    if (bytesRead < UreMsgBodyLength.MESSAGE_HEADER_LEN) 
     throw new IOException("Socket Read Failed - invalid bytesRead="+bytesRead); 


    int encodedLength = bytesRead; 
    if (encodedLength < 0 || (encodedLength & 3) != 0) 
     encodedLength = UreMsgBodyLength.MAXIMUM_MSG_LEN; 

    XdrBufferDecodingStream xdrOut = new XdrBufferDecodingStream (buffer, encodedLength); 
    xdrOut.beginDecoding(); 
    response.xdrDecode (xdrOut); 
    xdrOut.endDecoding(); 
    xdrOut.close(); 
    return response; 
    } 
    catch (ConnectException ex) 
    { 

    ioException = ex; 
    } 
    catch (IOException ex) 
    { 

    ioException = ex; 

    if (socket != null) 
    { 
     needResetPool = true; 
     try { socket.close(); } catch (Throwable t) {} 

     try 
     { 
     pool.invalidateObject (socket);   // Mark the socket as invalid 

     } 
     catch (Throwable t) 
     { 

     } 
     socket = null; 
    } 
    } 
    finally 
    {  
    if (socket != null) 
    { 
     try 
     { 
     pool.returnObject (socket); 
     } 
     catch (Throwable t) 
     { 

     } 
    } 
    } 

    if (attempts >= MAXIMUM_RETYR_BEFORE_RESET_POOL && needResetPool) 
    { 

    pool.clear (pool.getKey()); // clean all connect for the current server id 
    } 
    if (attempts >= MAXIMUM_RETRY) 
    { 

    throw ioException; 
    } 

    attempts++; 

} // while 

}

답변

1

나는 무엇을 놓치고?

서버가 EOS 읽기에 대한 응답으로 소켓을 닫지 않습니다 (read()는 -1을 반환합니다). 이 코드는 잘 처리하지 못합니다. CLOSE_WAIT는 피어가 연결을 닫았으며 로컬 시스템이 응용 프로그램이이를 종료하기를 기다리고 있음을 나타냅니다.

+0

안녕하세요. EJP가 EOS 용 조건 인 경우 위의 코드 & 장소에서 업데이트되었지만 나에게 적합하지 않습니다. 더 자세히 설명해 주실 수 있습니까? ....... if (bytesRead rahulpoorey

+0

@rahulpoorey 주석의 코드는 거의 판독 할 수 없지만 'if (bytesRead == -1)'여야합니다. 캐스트를 제거하십시오. 그리고 길이 테스트 전에 그 시험을 치십시오. 사실, * 길이 테스트를 제거합니다 : 그것을 루프로 변환하거나'DataInputStream.readFully()'를 사용하십시오. TCP는 언제나 당신에게 바이트 수를 제공 할 수 있습니다 : 당신은 잘못 놓인 기대가 실망 스러울 때'IOExceptions'를 던지지 않습니다. – EJP