views:

3643

answers:

3

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

A: 

isConnected will return false if the socket has been closed on the remote side.

AdamC
Unfortunately it doesn't. :-(
Cheekysoft
+8  A: 

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
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
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
+1  A: 

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."); }

Sangamesh