2014-09-24 94 views
-2

我正在嘗試創建多線程廣播服務器。我有一個名爲ClientHandler的類實現Runnable,並且此類的每個實例處理到客戶端的單個連接。我的服務器有一個名爲connectedClientsHashSet,它存儲對Socket類型對象的引用。所以我想要這個ClientHandler來處理到服務器的消息,但我希望服務器處理消息到客戶端,因爲我可以輕鬆地遍歷所有的客戶端並向每個客戶端發送一條消息。嘗試創建多線程廣播服務器 - 獲取IOException

我成功地使這臺服務器成爲一個工作的回聲服務器。這意味着,現在當我返工它能夠廣播消息,我敢肯定,一切都在服務器工作,除了這兩種方法:

  • ClientHandler中的run() - 方法:

  • broadcastMessage(字符串消息)::

    此方法只是等待輸入從客戶端它的處理,然後使用該方法將輸入發送到服務器10

    public void broadcastMessage (String message) { 
    
        Iterator<Socket> iterator = this.connectedClients.iterator(); 
    
        while (iterator.hasNext()) { 
         Socket currentSocket = iterator.next(); 
         try (     
          PrintWriter out = 
           new PrintWriter(currentSocket.getOutputStream(), true); 
         ) { 
          out.println("Server: " + message); 
    
          out.close(); 
    
         } catch(IOException e) { 
          System.err.println("Got an IOException error while reading or writing from/to client"); 
         } 
        } 
    } 
    

    此方法屬於服務器類,並且能夠當我創建一個ClientHandler服務器類中,像這樣使用這種方法我沿着到服務器類的實例的引用傳遞:new ClientHandler(clientSocket, this)).start();

我可以從客戶端發送一條消息到服務器並獲得響應,但之後立即得到我的「ClientHandler中出現IOException」 - 錯誤,程序關閉。爲什麼?

而這正在思考正確的方式來實現我想要實現的?

在此先感謝。請告訴我,我是否意外地遺漏了一些重要的信息。

編輯:下面是來自IOException異常堆棧跟蹤:

java.net.SocketException: socket closed 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(Unknown Source) 
    at java.net.SocketInputStream.read(Unknown Source) 
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source) 
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source) 
    at sun.nio.cs.StreamDecoder.read(Unknown Source) 
    at java.io.InputStreamReader.read(Unknown Source) 
    at java.io.BufferedReader.fill(Unknown Source) 
    at java.io.BufferedReader.readLine(Unknown Source) 
    at java.io.BufferedReader.readLine(Unknown Source) 
    at chat.ClientHandler.run(ChatServer.java:120) 
    at java.lang.Thread.run(Unknown Source) 
+1

什麼保護'connectedClients'在您嘗試迭代它時被修改? – 2014-09-24 11:22:27

+2

關閉流會在下次嘗試使用它們時導致IOException。請注意,'Socket.getInputStream()'會爲你提供同一個流實例,而不是新創建的實例。 – Fildor 2014-09-24 11:23:26

+0

@DavidSchwartz沒什麼,我猜。但我想這更像是一個一致性問題,而不是導致我的問題的原因?但是,是的,這也需要修復。 – 2014-09-24 11:31:43

回答

1

關閉流將導致IOException異常在明年嘗試使用它們。請注意,Socket.getInputStream()將爲您提供同一個流的實例,而不是新創建的實例。

確保InputStream,OutputStream和Socket本身只在完成通信後才關閉。

+0

謝謝!我不知道'Socket.getInputStream()'只給我一個流的實例。除去我的關閉聲明以及不使用「試用資源」聲明,從而阻止流太早關閉,這個訣竅。 – 2014-09-24 13:16:18