簡體   English   中英

如何向多個用戶發送消息?

[英]How to send messages to multiple users?

本質上,我有一個基本的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();
  }
}

您可以通過提供一個持有人來容納所有客戶的方式進行一些修改。 可以是List實現。 然后,您可以編寫一個廣播方法並調用它,而不是out.println() 在這種方法中,您將順便做類似的事情。

此外,您應該研究觀察者模式以有效地實現此目的,此外,您還將對設計模式有很好的了解。 另一個有用的模式Mediator Pattern

每次在listenSocket創建新的ClientWorker時,請在所有客戶端工作人員都可以訪問的列表中保留對客戶端的引用(無論是全局客戶端,還是最好在創建時傳遞給他們)。 當客戶收到一條消息時,它可以遍歷列表並將消息發回給每個工作人員。 在添加/刪除/迭代此列表時,您將需要小心,因為您將要運行很多線程,所有線程都可以嘗試同時訪問它。

另外,為了正確textArea.appendClientWorker應該從EDT(而不是從客戶端的線程)訪問Swing組件(例如textArea.append中的ClientWorker )。 有關SwingUtilities.invokeLater請參見javadocs。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM