开发者

How to send messages to multiple users?

Essentially I have a basic Java Socket server as you can see below. It allows multiple users to connect and when they send a message to it, it returns it back. However I was wondering how I could edit it so if a user sends a message to it, rather than just sending it back it sends it to everyone connected? So a basic chat server. Any help would be greatly appreciated :)

import java.awt.Color;
import java.awt.Bord开发者_StackOverflowerLayout;
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();
  }
}


You can add a little modification by providing a holder to hold all the clients. Can be a List implementation. Then you could write a broadcast method and invoke that instead of out.println(). In that method you would be doing the similar thing by the way.

Moreover, you should look into Observer Pattern to implement this effectively, plus you will get a good understanding of a design pattern too. Another pattern that would be helpful here is, Mediator Pattern.


Every time you create a new ClientWorker in listenSocket, keep a reference to the client in a list that all the client workers have access to (whether global or - preferably - passed into them when they're created). When a client receives a message, it can cycle through the list and send the message back out to each worker. You will need to be careful when adding/removing/iterating through this list, since you're going to have a lot of threads running that could all try and access it at the same time.

Also, for correctness your access to Swing components (such as textArea.append in ClientWorker) should be done from the EDT rather than from the client's thread. See the javadocs for SwingUtilities.invokeLater.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜