[英]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.append
, ClientWorker
应该从EDT(而不是从客户端的线程)访问Swing组件(例如textArea.append
中的ClientWorker
)。 有关SwingUtilities.invokeLater
请参见javadocs。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.