88

How do you detect if Socket#close() has been called on a socket on the remote side?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
Kevin Wong
  • 14,656
  • 11
  • 42
  • 52

4 Answers4

65

The isConnected method won't help, it will return true even if the remote side has closed the socket. Try this:

public class MyServer {
    public static final int PORT = 12345;
    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(PORT);
        Socket s = ss.accept();
        Thread.sleep(5000);
        ss.close();
        s.close();
    }
}

public class MyClient {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket s = SocketFactory.getDefault().createSocket("localhost", MyServer.PORT);
        System.out.println(" connected: " + s.isConnected());
        Thread.sleep(10000);
        System.out.println(" connected: " + s.isConnected());
    }
}

Start the server, start the client. You'll see that it prints "connected: true" twice, even though the socket is closed the second time.

The only way to really find out is by reading (you'll get -1 as return value) or writing (an IOException (broken pipe) will be thrown) on the associated Input/OutputStreams.

WMR
  • 12,661
  • 5
  • 35
  • 30
  • 1
    In your example the server doesn't close the TCP connection gracefully (RST is sent and that's it). If you call close() on the client socket, the connection is closed gracefully. You could see this by the different outcome of the read operation: SocketException thrown vs. read returning -1. – Alexander Sep 30 '08 at 22:12
  • BTW, thanks for reminding me of this "mystery" in the way Java sockets work. I've asked a follow-up question as a result: http://stackoverflow.com/questions/155243/why-is-it-impossible-without-attempting-io-to-detect-that-tcp-socket-was-gracef – Alexander Sep 30 '08 at 23:41
  • 4
    The only way to find out is to write. Reading from an abruptly closed socket might not always return -1. http://stackoverflow.com/a/6404085/372643 – Bruno Dec 12 '11 at 15:02
  • @Bruno Please elaborate why a closed socket might not always return -1. – Pacerier Jul 16 '12 at 18:22
  • 1
    @Pacerier, see the link I posted. Essentially, there's no difference between a connection that doesn't send anything and one that's just dead (if you're not using TCP keep-alive). You can only detect a closed connection by writing to it. – Bruno Jul 16 '12 at 18:25
  • @Bruno See my comments over there: http://stackoverflow.com/questions/6404008/how-to-detect-a-tcp-socket-disconnection-with-c-berkeley-socket/6404085#comment-15210567 – Pacerier Jul 16 '12 at 19:01
  • 14
    Why does this have so many upvotes :/ It really does not even answer the questions, it is just explaining _what will not work_... – Matt Clark Jan 14 '16 at 01:34
30

Since the answers deviate I decided to test this and post the result - including the test example.

The server here just writes data to a client and does not expect any input.

The server:

ServerSocket serverSocket = new ServerSocket(4444);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
while (true) {
  out.println("output");
  if (out.checkError()) System.out.println("ERROR writing data to socket !!!");
  System.out.println(clientSocket.isConnected());
  System.out.println(clientSocket.getInputStream().read());
        // thread sleep ...
  // break condition , close sockets and the like ...
}
  • clientSocket.isConnected() returns always true once the client connects (and even after the disconnect) weird !!
  • getInputStream().read()
    • makes the thread wait for input as long as the client is connected and therefore makes your program not do anything - except if you get some input
    • returns -1 if the client disconnected
  • out.checkError() is true as soon as the client is disconnected so I recommend this
glenneroo
  • 1,908
  • 5
  • 30
  • 49
Thorsten Niehues
  • 13,712
  • 22
  • 78
  • 113
  • 27
    checkError() is true as soon as an error has been detected when writing, and no sooner. It certainly does not become true as soon as the client disconnects. -1 – user207421 Apr 08 '13 at 00:47
13

You can also check for socket output stream error while writing to client socket.

out.println(output);
if(out.checkError())
{
    throw new Exception("Error transmitting data.");
}
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Sangamesh
  • 147
  • 1
  • 2
-12

The method Socket.Available will immediately throw a SocketException if the remote system has disconnected/closed the connection.