我怎样才能中断一个ServerSocket的accept()方法?

在我的主线程中,我有一个while(listening)循环,它在我的ServerSocket对象上调用accept() ,然后启动一个新的客户端线程,并在接受新客户端时将其添加到Collection。

我也有一个pipe理线程,我想用来发出命令,如“退出”,这将导致所有的客户端线程closures,closures自己,closures主线程,通过听到错误。

然而, while(listening)循环中的accept()调用会阻塞,并且似乎没有任何方法来中断它,所以while条件不能被再次检查并且程序不能退出!

有没有更好的方法来做到这一点? 或者以某种方式来中断阻止方法?

您可以从另一个线程调用close() ,并且accept()调用将抛出一个SocketException 。

在accept()上设置超时时间,那么在指定的时间之后,呼叫将超时阻塞:

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

设置阻塞套接字操作的超时值:ServerSocket.accept(); SocketInputStream.read(); DatagramSocket.receive();

必须在进入阻止操作之前设置该选项才能生效。 如果超时过期并且操作将继续阻塞,则引发java.io.InterruptedIOException。 在这种情况下,套接字未closures。

在ServerSocket上调用close()一个选项?

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

closures这个sockets。 任何当前在accept()中被阻塞的线程都会抛出一个SocketException。

您可以创build“void”套接字用于中断serversocket.accept()

服务器端

 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 // ... } } 

破解服务器周期的方法

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

serversocket.close()抛出exception的原因是因为你有输出stream或inputstream附加到该套接字 。 通过首先closuresinput和输出stream,可以很好地避免这种exception。 然后尝试closuresserversocket。 写一个简单的方法

 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(); } } 

我可以通过从任何地方调用这个方法closures任何套接字,而不需要处理任何exception。

另一件你可以尝试的更清洁的方法是在accept循环中检查一个标志,然后当你的pipe理线程想要终止接受的线程阻塞时,设置标志(使线程安全),然后创build一个客户端套接字连接到监听套接字。 接受将停止阻塞并返回新的套接字。 你可以制定一些简单的协议,告诉监听线程干净地退出线程。 然后closures客户端的套接字。 没有例外,更干净。