Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Socket isClosed() returns false after client disconnected [duplicate]

Tags:

java

sockets

In my java application, I have a TCP server which sends data generated in my app to all connected clients. For each new socket, I create a new thread. Following is the thread code.

    public void run() {
        try {
            PrintStream printStream = new PrintStream(socket.getOutputStream(), true);
            while (true) {
                if (socket.isClosed()) {
                    break;
                }
                synchronized (DataSource.getInstance()) {
                    printStream.println(DataSource.getInstance().getData());
                    try {
                        DataSource.getInstance().wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Data generating thread writes to DataSoure when new data is available and calls notifyAll() so all threads which handles connected sockets wake up and send available data to clients.

My problem is, even if a client disconnected, socket.isClosed() returns true. So the thread which handles the socket never gets terminated.

Why does this happen? How can I exit the thread when a client gets disconnected?

like image 986
Lahiru Chandima Avatar asked May 31 '15 15:05

Lahiru Chandima


1 Answers

There is no "disconnect" with TCP. A peer can only indicate that it does not want to send anything more (send FIN) but this does not mean that it does not want to receive anything. The other end only realizes that read is unwanted too once it tries it and gets a RST back.

If you take the "don't want to read" as an indicator that the client closed (you might if the application protocol is this way) then you can test if the peer "disconnected" by simply reading from the socket. The system call then returns no error but 0 bytes and this means that there will be no more data from the peer. In Java this case gets translated into an EOFException.

Apart from that a socket does not get closed automatically - only explicitly. isClosed only returns true once the socket is explicitly closed on your local end, not the peer's end. And isConnected will also not tell you if the other end "disconnected", it will only tell you if your end did connect to the peer.

See also Java Socket API: How to tell if a connection has been closed?.

like image 154
Steffen Ullrich Avatar answered Nov 10 '22 13:11

Steffen Ullrich