I have the following structure for TCP client-server communication:
The question is how to gracefully stop the whole system? I can stop acceptor thread by just closing ServerSocket. It will cause accept() blocking call to throw SocketException. But how to stop workers? They read from stream and this call is blocking. According to this streams does not throw InterruptedException and thus worker cannot be interrupt()'ed.
It looks like I need to close worker socket from another thread, right? For this, socket should be made a public field or a method should be provided in worker to close it. Will this be nice? Or may be my whole design is flawed?
Your model works appropriately. The best way of interrupting non-interruptable constructs like IO is to close the socket. You can of course handle it before you go into a blocking state, but if the IO functions don't react to interruption you dont really have many good options
I would suggest using a boolean flag that the workers check periodically. Call the flag shouldStop
and if it's set to true, the worker cleans up and then dies. Following this method would allow you to implement some clean-up code so you don't leave resources hanging, etc.
You must not simply stop the server. The shutdown process might take a while while cleanup occurs because you need to ensure consistency.
Imagine a database server, if you simply shut it down while it is carrying out transactions you may leave its data inconsistent. That's why it typically takes a while to shutdown the server.
Closing the connections with the clients in the server side should cause the clients to get a EOF on their sides as far as I understand.
[EDIT-1]
I have delved a bit on the issue, just because I had not used sockets in a while and because I found the question interesting. I think as it has been well pointed out by others, the only option is to close the socket, which according got Javadocs will automatically close the input and output streams/
If there are chances that the thread is not IO-blocked, but in wait state or sleeping, I think it is still recommended to issue a Thread.interrupt() for the corresponding worker thread of a given socket; because there cannot be certainty of the blocking of state of every thread.
public static class IOServerWorker implements Runnable{
private Socket socket;
public IOServerWorker(Socket socket){
this.socket = socket;
}
@Override
public void run() {
String line = null;
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while( (line = reader.readLine())!=null){
System.out.println(line);
}
reader.close();
}catch(IOException e){
//TODO: do cleanup here
//TODO: log | wrap | rethrow exception
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With