2016-11-13 142 views
2

我正在嘗試創建多線程服務器,以便多個客戶端可以連接並可以接受服務。但是,如果需要,我不確定如何正確釋放我的資源。Java:正確關閉多線程服務器的套接字

我的服務器運行一個輸入線程(等待用戶輸入)和一個處理線程(處理連接和用戶)。我在服務器類中打開一個ServerSocket並將其傳遞給我的處理線程。它看起來像這樣:

public class ClientConnector implements Runnable { 

private ServerSocket serverSocket; 

public ClientConnector(ServerSocket serverSocket) { 
    this.serverSocket = serverSocket; 
} 

@Override 
public void run() { 
    ExecutorService tcpExecutor = Executors.newCachedThreadPool(); 

    while (!serverSocket.isClosed()) { 
     Socket clientSocket = null; 

     try { 
      clientSocket = serverSocket.accept(); 
     } catch (IOException e) { 
      System.err.println("could not accept connection"); 
     } 

     if (clientSocket != null) { 
      tcpExecutor.execute(new ClientHandler(clientSocket); 
     }   
    } 
} 
} 

如果我要退出,我只是在我的服務器類運行這個方法來關閉的ServerSocket:

public void exit() { 
    try { 
     serverSocket.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

這應該引起接下來的ServerSocket.accept()調用拋出異常,並且由於套接字關閉,循環停止。

我的問題是 - 是否關閉ServerSocket隱式關閉使用它創建的ClientSockets?或者我應該確保手動關閉每一個打開的ClientSocket?如果是這樣的話,有沒有一種簡單的方法可以做到這一點,而不是保存每一個連接到服務器的連接?

+0

問題是,在我們關閉服務器套接字時偶然發生的任何套接字都打開,因爲它們被阻塞等待來自客戶端的輸入。他們是一種奇怪的封鎖,甚至不能被打斷。即使發送一個空數據包以解除阻塞套接字的技巧也不行,因爲它們正在等待與第三方建立的連接,因此您無法在這些連接中插入空數據包。那麼,你有沒有找到解決辦法? –

回答

0

是否關閉ServerSocket隱式關閉使用它創建的ClientSocket?

不,它對它們沒有影響。

或者我應該確保手動關閉每一個打開的ClientSocket?

是的,你應該這樣做,無論如何,在每個處理程序線程。

如果是這樣,有沒有一種簡單的方法來做到這一點,而不是保存每個連接到服務器的某個地方?

只需強制讀取超時並關閉超時的每個套接字。這是任何服務器的正常部分。您不必收集插座或採取任何特殊措施關閉它們。

0

不,它不。它只是關閉了ServerSocket意味着無法建立新的連接。現有的開放式套接字仍將繼續工作。

沒有「簡單」的方法來關閉所有開放的套接字,因爲它並不是真的很難開始(或者如果你發現作爲網絡編程中的一個難題,有一些奇怪的事情發生)。

0

讓客戶端處理程序線程在處理結束時關閉客戶端套接字。

相關問題