我怎样才能中断一个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客户端的套接字。 没有例外,更干净。