Client disconnect check on Java TCP server - output only

I have a Java TCP server which, when a client connects to it, displays a message to the client every 30 seconds. This is a strict requirement that the client does not send any messages to the server and that the server does not send data other than 30 second interval messages to the client.

When I disconnect the client, the server does not understand this until the next time it tries to write to the client. Therefore, the server may take up to 30 seconds for the server to recognize the disconnect.

What I want to do is to check for disconnection every few seconds, without waiting, but I'm not sure how to do it, given that: a) the server does not receive from the client and b) the server cannot send other data. Can someone please shed light on this? Thanks.

+4
source share
2 answers

Despite the fact that your server does not β€œreceive” from the client, non-blocking reads on the client socket will tell you that there is either nothing to read (as you expect) or disconnect the client.

If you use NIO, you can simply use the non-blocking Selector loop (with non-blocking sockets) and write only your 30 seconds. If a SelectionKey is read and reading on SocketChannel returns -1, you know that the client has disconnected.

EDIT: Another approach with locking is to simply choose with a 30 second timeout. Any disconnection of the client will lead to the fact that the choice will return, and you will find out which of them are through the readable set. An additional thing you will need to do is keep track of how long you have been locked in the selection in order to find out when to record at 30 seconds (setting a timeout for the next delta selection).

Big Edit: After talking to Myn below, offering a complete example:

 public static void main(String[] args) throws IOException { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(4444); } catch (IOException e) { System.err.println("Could not listen on port: 4444."); System.exit(1); } Socket clientSocket = null; try { clientSocket = serverSocket.accept(); } catch (IOException e) { System.err.println("Accept failed."); System.exit(1); } // Set a 1 second timeout on the socket clientSocket.setSoTimeout(1000); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader( clientSocket.getInputStream())); long myNextOutputTime = System.currentTimeMillis() + 30000; String inputLine = null; boolean connected = true; while (connected) { try { inputLine = in.readLine(); if (inputLine == null) { System.out.println("Client Disconnected!"); connected = false; } } catch(java.net.SocketTimeoutException e) { System.out.println("Timed out trying to read from socket"); } if (connected && (System.currentTimeMillis() - myNextOutputTime > 0)) { out.println("My Message to the client"); myNextOutputTime += 30000; } } out.close(); in.close(); clientSocket.close(); serverSocket.close(); } 

It is worth noting that PrintWriter really moves you far from the actual socket, and you will not catch the socket disconnecting from the record (it will never throw an exception, you need to manually check it with checkError() ) Instead, you can use BufferedWriter instead (you need to use flush() to output the output) and treat it like a BufferedReader to catch a disco when recording.

+9
source

If you manage multiple clients, then, I think, you would use non-blocking sockets (if then do not think about using blocking). You can use Selector to monitor all connected sockets to check if they are readable or writable, or if there is some error in this socket. When a client disconnects, your selector will mark this socket and return. For more google help "Socket Select Function"

+1
source

Source: https://habr.com/ru/post/1343207/


All Articles