2016-04-03 18 views
1

私はサーバークライアントアプリケーションを設定しました。 (HOMEWORK)チャット:サーバー上のすべてのクライアントにメッセージを送信

これまでのところ、複数のクライアントをサーバーに接続し、クライアントが送信したメッセージをサーバーに集約させる方法と、クライアントのメッセージをクライアントに送り返して表示させる方法を考えましたチャットウィンドウに表示されます。

私の問題は、複数のクライアントにメッセージを送信しようとしています。 私はServerSocketとSocketライブラリのみを使用できます。

私は2つのクライアントがサーバーに接続していると言います。 1つのクライアントがメッセージを送信すると、そのメッセージはクライアントのチャットに表示されます。 2番目のクライアントはメッセージを送信し、1番目のクライアントはメッセージを受信せず、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>、ここでStringはクライアント識別子です)、メッセージを送信します。

+0

私はあなたの最初の2つの文を正確に取得しません。クライアントはどのようにGUIスレッドに書き込むことができますか?私が今やっていることではない?私は誤解して申し訳ありません。 実際のソケットの代わりに "out"を格納することをお勧めしますか?私は午前中にそれを試し、それがうまくいくなら、良い提案をしてくれるでしょう。また、間違いなくHashMapを使用します。 – mrybak3

+1

@ mrybak3:はい、PrintStreamでラップされたOutputStreamを保持するユーティリティクラスのOutputStreamsまたはより可能性の高いオブジェクトです。 –

+0

素晴らしいです、ありがとうございます – mrybak3

関連する問題