2015-01-12 266 views
-1

我在Java中的多線程TCP服務器,它允許從多個客戶端的連接,並開始一個新的ServerThread每個連接的客戶端中斷服務線程特定的超時,客戶端關閉其套接字。我如何中斷與客戶端連接的ServerThread? clientsocket.isClosed()!clientSocket.isConnected()由於某種原因不起作用。當客戶端關閉TCP連接

最後,我把它用下面的代碼片段工作(解決辦法是在資源塊的插座和無盡in.readLine() == null):

服務器類

public void run() { 
    while (!Thread.currentThread().isInterrupted()) { 
     try { 
      // Create a new thread for each incoming connection. 
      Socket clientSocket = serverSocket.accept(); 
      ServerThread serverThread = new ServerThread(clientSocket, this); 
      serverThread.start(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

ServerThread類:

public void run() { 
    try (Socket socket = clientSocket; // Enable auto-close for socket... 
     PrintWriter out = ...; BufferedReader in = ...;) { 

     ... 

     while (!clientSocket.isClosed() && !isInterrupted()) { 
      if (in.readLine() == null) { 
       break; 
      } 
     } 
     System.err.println("Client with port " + clientSocket.getPort() + " closed connection to server."); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

客戶端類:我使用與ServerThread類中的資源塊相同的嘗試

+2

1.您根本沒有多線程服務器。你應該調用'serverThread.start()',而不是'serverThread.run()'。目前你根本沒有創建任何真正的線程。 2. isClosed()和isConnected()方法告訴你有關你的套接字的狀態,而不是關於連接的狀態。當對方斷開連接時,它們不會奇蹟般地變爲虛假。 3.你不需要中斷ServerThread。在這種情況下從套接字讀取返回流的結束:你在測試嗎? – EJP

+0

但是,如果我不中斷ServerThread,一段時間後會有大量的ServerThreads。 – jannnik

+0

線程本身在讀取時識別流結束,或在寫入時識別IOException,或者讀取超時,並關閉它們的套接字並退出。這就是所有Java阻塞模式服務器的工作原理。您需要閱讀Java教程的自定義網絡部分。 – EJP

回答

2

如果客戶端在不發送明確的FIN的情況下關閉TCP套接字(例如,如果客戶端崩潰),那麼在下一次嘗試向客戶端發送數據包之前服務器不會知道它(此時客戶端將發送一個RST包來告訴服務器套接字已關閉)。

假設您可以控制客戶端和服務器代碼,檢查連接的最可靠方法是在兩者之間實現心跳機制,以便它們定期ping它們之間的一小段數據以檢查連接。

+0

謝謝,您能否解釋在關閉連接之前如何從客戶端發送FIN? – jannnik

+0

你使用標準的Java嗎?它*應該*發送一個FIN,當你調用socket.close()我相信。你需要檢查Wireshark之​​類的東西,看看底下發生了什麼。 – Paolo

+0

是的,我使用標準的Java。我是否需要調用特定的方法從客戶端接收FIN? – jannnik

0

保持活動套接字選項是觀察持久性TCP連接的標準方式。 如果您的服務器在中止期間處於阻塞讀取操作,您將得到java.io.IOException:讀取失敗。在異步情況下,您將收到帶有-1的讀取密鑰。 在寫狀態中,您將獲得:通過peer重置連接:套接字寫入錯誤。 如果連接不可恢復,只處理異常或錯誤代碼以關閉線程。

+0

他問如何檢測客戶端何時關閉套接字,並且這不會回答它。 – EJP