How to unlock a thread blocked on ServerSocket.accept ()?

I have a server thread with this code:

public void run() { try { ServerSocket server; EneaLog.printLog("Server is running."); server = new ServerSocket(this.portnumber); while (true) { new EneaServerConnection(server.accept(), this.project,stopped).start(); if (stopped) { EneaLog.printLog("Server safe-shutdown completed."); EneaLog.printLog("Hi!"); server.close(); return; } } } catch (IOException ex) { Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex); project.getExceptionHandler().handler(ex); } } 

and stop method:

 public void shutdown() { EneaLog.printLog("Server shutdown NOW!"); stopped = true; } 

I want shutdown to be able to unlock the thread waiting for the .accept () server, otherwise I have to wait for the connection until the server shuts down.

I cannot do server.close () in shutdown () because I have to signal to the registered client that the server is going down.

Any ideas?

+6
java sockets
source share
5 answers

I am trying to create my code so that it can be "turned off" with interruption. This is mainly due to the fact that within the framework of the Executor , the Java concurrency package uses interrupt to cancel the tasks that are performed. In addition, the shutdown task should not know any internal components of the task being killed.

However, an accept call will not respond to an interrupt if it is not created using ServerSocketChannel . The created server with the ServerSocket constructor will ignore interrupts, and I did not find a way to reconfigure it.

If you cannot change the code creating the server, create another thread to call close on the server socket. This will also throw an exception in the thread blocked on accept , regardless of the method used to create the server socket.

This turns out to be a real pain when using SSL. The JSSE socket is not created from the InterruptibleChannel and will not respond to a simple interrupt in the stream.


I just noticed that the question says that the server cannot be closed without notifying the client. Successful interruption of a socket leads to its closure.

When accept is invoked, this should not be a problem since the client is not connected if the server socket is blocked in accept. This should only be a problem for Socket instances that represent current connections.

If this does not meet the notification requirements, a rework may be required to use the NIO ServerSocketChannel in non-blocking mode.

+4
source share

You should be able to close the socket from another thread.

+2
source share

Not a single interrupt (depending on breakpoints, just like cancellation depends on cancel points), does not close it (accept does not respond to closing its file descriptor). You will need to contact accept (try sendto with a disconnect notification) to notify it so that it does not continue to receive. At least this applies to Linux; I donโ€™t know how it was on other platforms.

+2
source share

I ran into the same problem. My working decisions are to close the ServerSocket object (serverSocket.close ()); this will cause the accept () method to throw the SocketException you want to throw.

Vincent

+1
source share

Have you tried Thread.interrupt () ?

If this thread is blocked in an I / O operation on an intermittent channel, the channel will be closed, the state of interruption of the stream will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in the Selector, then the interruption of the status of the stream will be set, and it will return immediately after selection, possibly with a non-zero value, as if the selector called the awakening method.

0
source share

All Articles