1

I know that there have been quite similar questions in the past and I studied most of them but couldn't manage to get my code working.

I have a TCPIP-Server written in Java and a client Android app.

When I am turning off my WLAN on my phone I obviously don't have any connection to my server but the server doesn't notice this.

How I read on the server

try {
    bufferSender = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    //this while it's like a listener for messages
    String message = null;
    while (running) {
        try {
            message = in.readLine();
            if (message == null)
                System.out.println(this.user.getUsername() + " left the room.");
        } catch (IOException e) {
            System.out.println("Error reading message: " + e.getMessage());
            running = false;
            managerDelegate.userDisconnected(this);
        }

        if (message != null && managerDelegate != null) {
            user.setMessage(message);
            System.out.println("message:" + message);

            // notify message received action
            managerDelegate.messageReceived(user);
        }
    }

} catch (Exception e) {
    System.out.println("S: Error");
    e.printStackTrace();
}

I have read that I should get an error when trying to read a Message from the Client. But I don't get any error.

So I tried to send a message from the Server to the Client every X seconds. This is how I send it:

public void sendMessage(String message) {
    if (bufferSender != null && !bufferSender.checkError()) {
        bufferSender.println(message);
        bufferSender.flush();
    } else {
        System.out.println("ERROR");
    }
}

But again, nothing happens. I don't get any error by sending a message to the client even if the client has no connection to the internet.

What am I doing wrong?

progNewbie
  • 4,362
  • 9
  • 48
  • 107

2 Answers2

2

You should set timeouts on your sockets. By default, they will wait forever if the connection had no opportunity to tell the other side that it was closing the connection.

socket.setSoTimeout(timeout)

You should set timeouts on both the client and server end of the connection.

Ownaginatious
  • 787
  • 4
  • 14
  • Untrue. When the peer disconnects the receiver wil get an end of stream indication. Timeouts are a good idea, but not for this reason. – user207421 Nov 18 '15 at 21:16
  • How can they get an end of stream notification if the socket was not closed cleanly? – Ownaginatious Nov 18 '15 at 21:18
  • 1
    Very much true. Clients that simply disappear don't send the required termination request (FIN). TCP connections can in theory be completely idle with neither side sending / receiving with no packets that need to be acked forever. But IRL you'll get problems with NAT routers because they drop you from their table because they assume the connection is gone. So to get a reliable long standing TCP connections, you'll have to manually do keep alive packets so that there is a) something to timeout and b) something that keeps routers aware of your connection. – zapl Nov 18 '15 at 21:25
  • How do I set a timeout? Is timeout set in seconds? milliseconds? And what happens when the timeout is reached? Can someone explain that a little bit further? Thank you very much! – progNewbie Nov 18 '15 at 21:32
  • By using the method in my answer above on your socket instances. The timeout value is in milliseconds. See here: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#setSoTimeout(int) – Ownaginatious Nov 18 '15 at 21:36
  • @Ownaginatious: Thank you very much. How do I catch the exception which is thrown? Because I need to end my thread, when this exception gets thrown. – progNewbie Nov 18 '15 at 21:39
  • The exception will be thrown as a SocketTimeoutException. Here is an example of how it could be implemented on the server side of your code: http://pastebin.com/f49wBZVW. – Ownaginatious Nov 18 '15 at 21:57
  • @Ownaginatious: One last question: I edited this on my server and on my client. And at my server it works!! If the client diesconnects, the exception is thrown. But when I close the server (kill process). The client doesn't throw any exception, although I set the SoTimeout. Any suggestions? – progNewbie Nov 18 '15 at 22:42
  • @texNewbie Could you post some of your client code? – Ownaginatious Nov 18 '15 at 23:38
  • @Ownaginatious: I fixed it by checking if the readline() is null. This worked here. – progNewbie Nov 18 '15 at 23:46
1

When readLine() returns null you should stop reading. There will never be any more data.

Same applies if read() returns -1 or readXXX() throws EOFException, for any X.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • The strange thing is, it never returns null. That's my whole problem. – progNewbie Nov 18 '15 at 21:21
  • Because he assumed the connection was properly closed. If one end of the connection disappears, there will be no signal to the other end and it will continue waiting for more data. Turning off WLAN is an example of severing the connection uncleanly. Timeouts are the only way to resolve this. – Ownaginatious Nov 18 '15 at 21:23
  • I have the same problem, it never returns null or -1 when trying to read from the disconnected client.... – javac31 Jun 15 '21 at 09:32