How can I interrupt a ServerSocket accept() method?

In my main thread I have a while(listening) loop which calls accept() on my ServerSocket object, then starts a new client thread and adds it to a Collection when a new client is accepted.

I also have an Admin thread which I want to use to issue commands, like 'exit', which will cause all the client threads to be shut down, shut itself down, and shut down the main thread, by turning listening to false.

However, the accept() call in the while(listening) loop blocks, and there doesn't seem to be any way to interrupt it, so the while condition cannot be checked again and the program cannot exit!

Is there a better way to do this? Or some way to interrupt the blocking method?


You can call close() from another thread, and the accept() call will throw a SocketException.


Set timeout on accept(), then the call will timeout the blocking after specified time:

http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT

Set a timeout on blocking Socket operations:

ServerSocket.accept();
SocketInputStream.read();
DatagramSocket.receive();

The option must be set prior to entering a blocking operation to take effect. If the timeout expires and the operation would continue to block, java.io.InterruptedIOException is raised. The Socket is not closed in this case.


Is calling close() on the ServerSocket an option?

http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29

Closes this socket. Any thread currently blocked in accept() will throw a SocketException.


You can just create "void" socket for break serversocket.accept()

Server side

private static final byte END_WAITING = 66;
private static final byte CONNECT_REQUEST = 1;

while (true) {
      Socket clientSock = serverSocket.accept();
      int code = clientSock.getInputStream().read();
      if (code == END_WAITING
           /*&& clientSock.getInetAddress().getHostAddress().equals(myIp)*/) {
             // End waiting clients code detected
             break;
       } else if (code == CONNECT_REQUEST) { // other action
           // ...
       }
  }

Method for break server cycle

void acceptClients() {
     try {
          Socket s = new Socket(myIp, PORT);
          s.getOutputStream().write(END_WAITING);
          s.getOutputStream().flush();
          s.close();
     } catch (IOException e) {
     }
}

The reason ServerSocket.close() throws an exception is because you have an outputstream or an inputstream attached to that socket. You can avoid this exception safely by first closing the input and output streams. Then try closing the ServerSocket. Here is an example:

void closeServer() throws IOException {
  try {
    if (outputstream != null)
      outputstream.close();
    if (inputstream != null)
      inputstream.close();
  } catch (IOException e1) {
    e1.printStackTrace();
  }
  if (!serversock.isClosed())
    serversock.close();
  }
}

You can call this method to close any socket from anywhere without getting an exception.