Search code examples
javamultithreadingsocketstcpbufferedreader

BufferedReader in Java fails to trigger exception when trying to read from closed socket


I'm connecting a TCP socket and opening a buffered reader for I/O on that socket in its own thread, then reading data using readLine on the buffered reader:

try {
  socket = new Socket(targetHost, targetPort);
  ou = new PrintWriter(socket.getOutputStream(), true);
  in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

  while (true) {
    message = in.readLine();
    ...
    process the data
    ...
  }
} catch (Exception e) {
  e.printStackTrace();
  return;
}

This works fine as long as the connection is there. But when the other end of the TCP connection unexpectedly goes away, in about 75% of all cases, this thread never realises the other side has gone away, and any attempts to read from the buffered reader will simply yield a "null" string, but no exception is thrown, and I'm unable to shut the thread down because it doesn't know the other side has gone away. In about 25% of the cases, the thread is terminated (also without generating an exception) but that yields the desired outcome, I just need the thread to go away when the TCP connection drops.

I tried using this to figure out if the connection is alive:

boolean connected = socket.isConnected() && !socket.isClosed();

but that doesn't work, always returns true when the other side has gone away and the thread keeps on chomping.

Any ideas anyone?


Solution

  • The point is basically: "works as designed".

    The reader returning null actually means: "no more data; I am done here".

    See the javadoc:

    Returns: A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached

    In other words: the socket going closed is seen as "normal" operation here; thus there is no exception. In other words: you have to change your code to check if the result to readLine() returns null; and if so, you know what the socket is gone.