2016-04-03 83 views
1

我有一個服務器 - 客戶端應用程序集。 (HOMEWORK)聊天:發送消息給服務器上的所有客戶端

到目前爲止,我已經想出瞭如何讓多個客戶端連接到服務器,並讓服務器聚合客戶端發送的消息,並讓服務器將客戶端消息發送回客戶端並顯示它在聊天窗格中。

我的問題是試圖發送消息給多個客戶端。 我只允許使用ServerSocket和Socket庫。

假設我有2個客戶端連接到服務器。一個客戶端發送一條消息,該消息顯示在客戶端的聊天中。第二個客戶端發送消息,第一個客戶端不會收到它,第二個客戶端的聊天窗口顯示第一個客戶端的消息。

本質上,服務器正在發送相應客戶端未在聊天箱中顯示的最新消息,我不知道爲什麼或如何。

代碼服務器到客戶端通信:

Class CommunicationThread extends Thread { 

    //Vector containing all client sockets currently connected 
    //Held offsite, here for clarity 
    public Vector<Socket> socketVector; 

    public CommunicationThread (Socket clientSoc, Server ec3, Vector<Socket>socketVectorg) 
    { 
    //add new socket to vector, start thread 
    clientSocket = clientSoc; 
    socketVectorg.add(clientSocket); 
    this.socketVector = socketVectorg; 
    gui = ec3; 
    } 

    public void run() 
    { 
    System.out.println ("New Communication Thread Started"); 

    try { 
     //Client's chat box (output) 
     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), 
       true); 

     //Input line from client 
     BufferedReader in = new BufferedReader(
       new InputStreamReader(clientSocket.getInputStream())); 

     String inputLine; 

     while ((inputLine = in.readLine()) != null) { 
      System.out.println("Server: " + inputLine); 
      gui.history.insert(inputLine + "\n", 0); 

      //*************HERE IS MY ISSUE******************* 
      for(Socket s : socketVector){ 
       out = new PrintWriter(s.getOutputStream(), 
         true); 
       out.println(inputLine); 
      } 

      if (inputLine.equals("Bye.")) 
       break; 

      if (inputLine.equals("End Server.")) 
       gui.serverContinue = false; 

     } 

     out.close(); 
     in.close(); 
     clientSocket.close(); 
    } 
    catch (IOException e) 
    { 
    System.err.println("Problem with Communication Server"); 
    //System.exit(1); 
    } 
    } 
} 

我知道我重寫「走出去」,但我不認爲這是我的問題,所以它是在我的代碼,而我測試。

我的問題在上面的代碼中標出。矢量精確地存儲套接字ID,並且由於我基於矢量創建了一個新的PrinterWriter,因此我只會假定它將獲得相應客戶端的輸出字段,但它不會。

我的直覺是,它是一個線程或關閉輸出的問題,但我真的不知道。

任何建議表示讚賞。

+2

哦,主,請不要在構造函數的線程中調用'start()'。該對象尚未完全構建。構造函數返回後調用'start()';如果您需要強制執行此行爲,請使用靜態方法(工廠方法)。 – markspace

+0

已修復並注意到,謝謝 – mrybak3

+1

好吧,部分問題可能是您爲每行輸入創建了一個新的'PrintWriter'。這似乎「關閉」。另外,我在這個類中看到了GUI代碼。通常GUI運行在客戶端上,而不是服務器上。所以我只想確認你的代碼是服務器代碼。正確? – markspace

回答

1

你的問題在我看來,你想在輸入和輸出工作的客戶端套接字都在同一個地方,並沒有必要這樣做。客戶端套接字的輸出流可以在GUI線程中寫入,並且全部集中在一個地方。如果需要,您可以保留輸出流的集合,並且當您想要回復所有輸出流時,迭代整個集合(可能是字符串是某個客戶端標識符的HashMap<String, OutpuStream>)併發送消息。

+0

我不完全得到你的第2句話。如何在GUI線程中寫入客戶端?不是我現在在做什麼?對不起,如果我是誤會。 就這樣我清楚,你建議存儲「out」而不是實際的套接字?我會在早上嘗試一下,如果它能正常工作,一定會得到最好的答案,好的建議。也肯定會使用一個HashMap,謝謝。 – mrybak3

+1

@ mrybak3:是的,OutputStreams或一個工具類的更可能的對象,它包含一個包裝在PrintStream中的OutputStream。 –

+0

太棒了,非常感謝 – mrybak3

相關問題