2017-04-11 37 views
0

チャットクライアント/サーバープログラムで、接続されているすべてのクライアントにメッセージをブロードキャストできません。送信されたメッセージは、ArrayListを繰り返し処理していても元のサーバーに返されるようです。私はソケットのArrayListとパラメータとして読み取りメッセージを取り込み、各ソケットのPrintWriterを作成するメソッドを持っています。問題はクライアントクラス(私が間違っていると私に言い訳)と関係していると思いますが、何が分かりませんか。チャットプログラムでメッセージを送信したクライアントにメッセージが送信されています

クライアントクラス:

public class H7Client extends Thread implements ActionListener{ 

private JTextField jtfPortName = new JTextField(20); 
private JTextField jtfHostName = new JTextField(20); 
private String hostName; 
private int portNumber; 

private JTextArea jtaChat = new JTextArea("Send a message to the client", 15,40); 
private JTextArea jtaRecive = new JTextArea("WELCOME TO THE CHAT!", 15,40); 
private JTextField jtfUName = new JTextField("user"); 



public H7Client(){ 
    JFrame defaultFrame = new JFrame(); 

    JLabel jlPortName = new JLabel("Enter The Port number"); 
    JLabel jlHostName = new JLabel("Enter the Host name"); 
    JLabel jlUName = new JLabel("Enter a username"); 

    JButton jbSetSocketInfo = new JButton("Confirm Port and Host Info"); 
    JButton jbExit = new JButton("Exit"); 
    JButton jbSendText = new JButton("Send"); 

    jbSetSocketInfo.addActionListener(this); 
    jbExit.addActionListener(this); 
    jbSendText.addActionListener(this); 



    JPanel jpNorth = new JPanel(); 
    JPanel jpCenter = new JPanel(); 
    JPanel jpLabels = new JPanel(); 

    defaultFrame.add(jpNorth,BorderLayout.NORTH); 
    jpNorth.add(jbSetSocketInfo,BorderLayout.EAST); 
    jpNorth.add(jbSendText, BorderLayout.CENTER); 
    jpNorth.add(jbExit,BorderLayout.WEST); 


    defaultFrame.add(jpCenter,BorderLayout.CENTER); 
    jpCenter.add(jtaChat,BorderLayout.SOUTH); 
    jpCenter.add(jpLabels,BorderLayout.NORTH); 

    jpLabels.setLayout(new GridLayout(2,3)); 
    jpLabels.add(jlHostName); 
    jpLabels.add(jlPortName); 
    jpLabels.add(jlUName); 
    jpLabels.add(jtfHostName); 
    jpLabels.add(jtfPortName); 
    jpLabels.add(jtfUName); 

    defaultFrame.add(jtaRecive,BorderLayout.SOUTH); 

    defaultFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 


    defaultFrame.setLocationRelativeTo(null); 
    defaultFrame.setSize(800,800); 
    defaultFrame.setVisible(true); 

} 

public void setClientComms(String message){ 
    try{ 
     // open communications to the server 
     Socket s = new Socket(hostName, portNumber); 
     ClientThread ct = new ClientThread(s, message); 
    } 
    catch(IOException e){ 
     e.printStackTrace(); 
    } 
} 

class ClientThread extends Thread{ 

    public ClientThread(Socket sock, String msg) { 

     try { 

      // open input stream 
      InputStream in = sock.getInputStream(); 
      BufferedReader br = new BufferedReader(
        new InputStreamReader(in)); 

      // open output stream 
      OutputStream out = sock.getOutputStream(); 
      PrintWriter pout = new PrintWriter(
        new OutputStreamWriter(out)); 


      // write something to the server 
      pout.println(msg); 

      // make sure it went 
      pout.flush(); 

      // read something back from server 
      String incomingMessage = br.readLine(); 

      // print the something to the user 
      System.out.println("Message: " + msg); 
      //jtaChat.setText(""); 
      jtaRecive.append("\n" + msg); 


      // Send the terminating string to the server 
      pout.println("quit"); 
      pout.flush(); 

      // close everything 
      pout.close(); 
      br.close(); 
      sock.close(); 
     } catch (UnknownHostException uhe) { 
      System.out.println("What host you speak of?"); 
     } catch (IOException ioe) { 
      System.out.println("Bad IO?"); 
      ioe.printStackTrace(); 
     } 
    } 
} 

public void actionPerformed(ActionEvent event) { 
    if (event.getActionCommand().equals("Exit")) { 
     System.exit(0); 
    } else if (event.getActionCommand().equals("Send")) { 
     String chatMessage = jtaChat.getText(); 
     jtaChat.setText(""); 
     setClientComms(chatMessage); 


    } else if (event.getActionCommand().equals("Confirm Port and Host Info")) { 
     hostName = jtfHostName.getText(); 
     //NEED TO ADD IN WAY TO HANDLE IP ADDRESSES 
     portNumber = Integer.parseInt(jtfPortName.getText()); 
    } 
} 


public static void main(String [] args) { 

    new H7Client(); 


} 

}

サーバー・クラス:

public class H7Server{ 

public ArrayList<Socket> clients = new ArrayList<Socket>(); 

public static void main(String[] args){new H7Server();} 
public H7Server() 
{ 



    ServerSocket ss = null; 

    try { 
     System.out.println("getLocalHost: "+ InetAddress.getLocalHost()); 
     System.out.println("getByName: "+InetAddress.getByName("localhost")); 

     ss = new ServerSocket(16789); 
     Socket cs = null; 
     while(true){  // run forever once up 
      //try{ 
      cs = ss.accept();    // wait for connection 
      clients.add(cs); 
      ThreadServer ths = new ThreadServer(cs); 
      ths.start(); 
     } // end while 
    } 
    catch(BindException be) { 
     System.out.println("Server already running on this computer, stopping."); 
    } 
    catch(IOException ioe) { 
     System.out.println("IO Error"); 
     ioe.printStackTrace(); 
    } 

} // end main 

class ThreadServer extends Thread { 
    Socket cs; 

    public ThreadServer(Socket cs) { 
     this.cs = cs; 
    } 

    public void run() { 

      BufferedReader br; 
      String clientMsg; 
      try { 
       br = new BufferedReader(
         new InputStreamReader(
           cs.getInputStream())); 


       clientMsg = br.readLine();    // from client 
       System.out.println("Server read: " + clientMsg); 
       while(clientMsg != null) { 
        sendMessage(clientMsg); 
       } 

      } catch (IOException e) { 
       System.out.println("Inside catch"); 
       e.printStackTrace(); 
      } 


    } 

    public synchronized void sendMessage(String s){ 
     try{ 
      for(Socket sock: clients) { 
       PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream())); 

       pw.println(s); 
       pw.flush(); 
      } 
     } 
     catch(IOException e){ 
      e.printStackTrace(); 
     } 


    } 

} // end class ThreadServer 

}

答えて

0

あなたが疑われるとして、クライアントクラスの両方に問題があります、とまた、サーバークラス。修正する必要があるのは2つあります。

まず、サーバーからメッセージを受け取りますが、何もしません。クライアントはClientThreadのコンストラクタのtryブロックにincomingMessageを受け取りますが、使用されていません。可能な修正は、それをjtaReceiveに追加し、もう一方の追加を削除することですが、これを行わないでください。

リアルタイムチャットの場合、クライアントには少なくとも2つのスレッド(メッセージを送信するスレッドと受信するメッセージがあるかどうかを常に確認するスレッド)が必要です。おそらく、これはClientThreadで達成しようとしていたものですが、残念ながらうまくいきません。間違ったコードに加えて、ClientThreadを使用するとThreadが作成されますが、実際には実行されることはありません。 runメソッドで、サーバーから常にメッセージを受け取る永続的なwhileループを含むスレッドが必要です。 (あなたが好きなものに名前を変更することができます)

class ReceiverThread extends Thread { 

    private BufferedReader s; 

    public ReceiverThread(Socket sock) throws IOException { 
     s = new BufferedReader(new InputStreamReader(sock.getInputStream())); 
    } 

    @Override 
    public void run() { 
     while (true) 
      try { 
       String message = s.readLine(); 
       // ...code to do whatever with message... 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
    } 

} 

さらに、あなたも開いたままにソケットを作成する必要がありますが、ホストとポートの情報を確認したときに(多分ソケットを使用してこのスレッドを作成して起動します。一つの実装はこれです)。

サーバークラスの問題は、私たちすべてを惹きつけてしまう問題です。悪名高いのはConcurrentModificationExceptionです。それはhereについて読むことができますが、基本的にこの例外は、あなたが想定していないときにデータ構造を変更(追加、削除など)するとスローされます。問題のデータ構造はArrayListSocketであり、メッセージが送信されるときのループはfor-eachです。基本的には、そのループが実行されている間にSocketを作成するwhileループがArrayListにループを追加して例外をスローしています。修復するには、forループのときに、forループを削除するか、forループが終了するまでwhileループを保持するか、forループが追加されるときにQueueのソケットを追加することによって、ArrayListの変更を停止する必要がありますこれは多くの方法があります。

あなたのサーバーはテストのためだけに1つのメッセージを受信すると仮定していますが、複数のメッセージをチャットできると決めた場合は、クライアントクラスに使用する余分なスレッドを使用する必要があります。

幸運の:)。

注:時間がかかりそうなものやアプリケーションGUIが実際にフリーズするようなものについては、AWT threadactionPerformedというスレッド)を使用することをお勧めします。

+0

本当にありがとうございました。これは本当に助けになりました。非常に遅い応答のために申し訳ありません! –

関連する問題