2010-06-06 79 views
117

在我的主線程中,我有一個while(listening)循環,它在我的ServerSocket對象上調用accept(),然後啓動新的客戶端線程,並在接受新客戶端時將其添加到集合中。如何中斷ServerSocket的accept()方法?

我也有一個管理線程,我想用它來發出命令,比如'exit',這會導致所有的客戶端線程關閉,關閉它,關閉主線程,通過轉向監聽假。

但是,在while(listening)循環塊中調用accept(),並且似乎沒有任何方法來中斷它,所以while條件不能再次檢查並且程序不能退出!

有沒有更好的方法來做到這一點?或者某種方式來中斷阻塞方法?

+1

請參閱http://stackoverflow.com/questions/2804797/java-stop-server-thread – CuriousPanda 2010-06-06 10:27:28

回答

119

您可以從另一個線程中調用close()accept()調用將拋出SocketException。在接受

+1

非常明顯,謝謝,甚至沒有發生在我身上!在退出循環後,我正在調用close()。 – lukeo05 2010-06-06 10:35:06

+4

奇怪的是,在文檔中沒有此信息:http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#accept%28%29方法未標記爲拋出SocketException 。它只在這裏提到http://download.oracle.com/javase/1.4.2/docs/api/java/net/ServerSocket.html#close%28%29 – 2011-04-07 12:57:15

+1

可以調用'close()',我的意思是它會拋出異常,所以有沒有其他方式(不會引發異常,也不是基於超時)來停止監聽請求? – Kushal 2012-06-07 13:13:14

24

設置超時(),則調用將指定的時間後超時阻塞:

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

設置超時阻斷插座操作: 的ServerSocket.accept(); SocketInputStream.read(); DatagramSocket.receive();

該選項必須在輸入阻止操作生效之前設置。如果超時過期並且操作將繼續阻塞,則引發java.io.InterruptedIOException。在這種情況下,套接字未關閉。

0

另一件事你可以嘗試這是清潔,是在接受循環檢查標誌,然後當你的管理線程想要殺死線程阻塞的接受,設置標誌(使它線程安全)然後與偵聽套接字建立客戶套接字連接。 accept將停止阻塞並返回新的套接字。 你可以制定一些簡單的協議,告訴監聽線程乾淨地退出線程。 然後關閉客戶端的套接字。 沒有例外,更乾淨。

3

原因serversocket.close()拋出例外是因爲你有爲OutputStream或InputStream的連接到插座。通過首先關閉輸入和輸出流,可以很好地避免這種異常。然後嘗試關閉serversocket。 編寫一個簡單的方法

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

我可以簡單地通過調用從任何地方這個方法沒有得到任何的異常處理關閉任何插座。

+4

輸入和輸出流不附加到'ServerSocket',而是附加到'Socket',我們正在討論關閉'ServerSocket'而不是'Socket',所以'ServerSocket'可以在不關閉'Socket'的情況下關閉。的溪流。 – icza 2014-09-03 05:42:16

3

您只需創建的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) { 
    } 
} 
相關問題