rahulpoorey
rahulpoorey

Reputation: 21

Java Server socket TCP connection stuck in CLOSE_WAIT state while client shutdown or client restart

While performing Client restart or shutdown,all socket connections are hang in CLOSE_WAIT on server side. XdrAble used to send serialized data into XDR streams. pool is object of standard KeyedSocketPool. MAXIMUM_RETRY,MAXIMUM_RETYR_BEFORE_RESET_POOL are constants defined to reset the pool connections. What I am missing while closing the connections?

public RESP call (REQ request, RESP response, int requestLength, int timeOut) throws Exception {
Socket 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

}

Upvotes: 2

Views: 4310

Answers (1)

user207421
user207421

Reputation: 310869

What am I missing while closing the connections?

The server isn't closing its sockets in response to reading EOS (read() returns -1). This code doesn't handle it well either. CLOSE_WAIT means that the peer has closed the connection and the local system is waiting for the application to close this end.

Upvotes: 1

Related Questions