如何向多个用户发送消息?

时间:2010-02-04 09:42:24

标签: java sockets

基本上我有一个基本的Java Socket服务器,如下所示。它允许多个用户进行连接,当他们向其发送消息时,它会将其返回。但是我想知道如何编辑它所以如果用户向它发送消息,而不是仅仅发送回来它将它发送给连接的每个人?所以基本的聊天服务器。任何帮助将不胜感激:)

import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;

import java.io.*;
import java.net.*;

class ClientWorker implements Runnable {
  private Socket client;
  private JTextArea textArea;

  ClientWorker(Socket client, JTextArea textArea) {
   this.client = client;
   this.textArea = textArea;   
  }

  public void run(){
    String line;
    BufferedReader in = null;
    PrintWriter out = null;
    try{
      in = new BufferedReader(new InputStreamReader(client.getInputStream()));
      out = new PrintWriter(client.getOutputStream(), true);
    } catch (IOException e) {
      System.out.println("in or out failed");
      System.exit(-1);
    }

    while(true){
      try{
        line = in.readLine();
//Send data back to client
         out.println(line);
         textArea.append(line);
       } catch (IOException e) {
         System.out.println("Read failed");
         System.exit(-1);
       }
    }
  }
}

class SocketThrdServer extends JFrame{

   JLabel label = new JLabel("Text received over socket:");
   JPanel panel;
   JTextArea textArea = new JTextArea();
   ServerSocket server = null;

   SocketThrdServer(){ //Begin Constructor
     panel = new JPanel();
     panel.setLayout(new BorderLayout());
     panel.setBackground(Color.white);
     getContentPane().add(panel);
     panel.add("North", label);
     panel.add("Center", textArea);
   } //End Constructor

  public void listenSocket(){
    try{
      server = new ServerSocket(4444); 
    } catch (IOException e) {
      System.out.println("Could not listen on port 4444");
      System.exit(-1);
    }
    while(true){
      ClientWorker w;
      try{
        w = new ClientWorker(server.accept(), textArea);
        Thread t = new Thread(w);
        t.start();
      } catch (IOException e) {
        System.out.println("Accept failed: 4444");
        System.exit(-1);
      }
    }
  }

  protected void finalize(){
//Objects created in run method are finalized when 
//program terminates and thread exits
     try{
        server.close();
    } catch (IOException e) {
        System.out.println("Could not close socket");
        System.exit(-1);
    }
  }

  public static void main(String[] args){
        SocketThrdServer frame = new SocketThrdServer();
    frame.setTitle("Server Program");
        WindowListener l = new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                        System.exit(0);
                }
        };
        frame.addWindowListener(l);
        frame.pack();
        frame.setVisible(true);
        frame.listenSocket();
  }
}

2 个答案:

答案 0 :(得分:0)

您可以通过提供持有人来保留所有客户端来添加一些修改。可以是List实现。然后你可以编写一个广播方法并调用它而不是out.println()。在那种方法中,顺便说一下你会做类似的事情。

此外,您应该考虑Observer Pattern来有效地实现这一点,此外您还将对设计模式有一个很好的理解。另一种有用的模式是Mediator Pattern

答案 1 :(得分:0)

每次在ClientWorker中创建新的listenSocket时,请在所有客户工作人员都可以访问的列表中保留对客户端的引用(无论是全局的还是 - 最好 - 当它们被传递到它们中时'创造了')。当客户端收到消息时,它可以遍历列表并将消息发送回每个工作人员。在添加/删除/迭代这个列表时你需要小心,因为你将要运行很多线程,所有线程都可以同时尝试访问它。

另外,为了正确起见,您应该从EDT而不是客户端的线程中访问Swing组件(例如textArea.append中的ClientWorker)。请参阅SwingUtilities.invokeLater的javadoc。