Java如何让服务器向每个连接的客户端发送消息

Java如何让服务器向每个连接的客户端发送消息,java,networking,chat,Java,Networking,Chat,我正在尝试创建一个聊天程序,其中客户端向服务器发送消息,然后服务器向所有连接的客户端发送该消息以显示该消息。 该程序可以工作,但当客户端只发送消息时,它会将消息接收回来,而其他连接的客户端则不会收到任何消息 客户端代码: public class Client { protected static JTextArea textArea = new JTextArea(20, 30); protected static String sendMSG, getMSG;

我正在尝试创建一个聊天程序,其中客户端向服务器发送消息,然后服务器向所有连接的客户端发送该消息以显示该消息。 该程序可以工作,但当客户端只发送消息时,它会将消息接收回来,而其他连接的客户端则不会收到任何消息

客户端代码:


public class Client {

    protected static JTextArea textArea = new JTextArea(20, 30);
    protected static String sendMSG, getMSG;

    public static void main(String[] args) throws IOException {
        String hostName = args[0];
        String Username = args[1];
        boolean sending = true;

        try (
            Socket socket = new Socket(hostName, 1010);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        ) {
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

            //frame setup
            JFrame frame = new JFrame("chat client");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            //text area
            JScrollPane scrollPane = new JScrollPane(textArea);

            //text field
            JTextField MSGText = new JTextField(5);

            //"send" button
            JButton sMSGB = new JButton("send");
            sMSGB.setPreferredSize(new Dimension(60, 30));
            sMSGB.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent event) {
                    sendMSG = MSGText.getText();
                    MSGText.setText("");
                    out.println("<" + Username + ">: " + sendMSG);
                }

            });

            //panel
            JPanel p = new JPanel();
            p.setLayout((new BoxLayout(p, BoxLayout.PAGE_AXIS)));
            p.add(Box.createVerticalStrut(5));
            p.add(scrollPane);
            p.add(Box.createVerticalStrut(5));
            p.add(MSGText);
            p.add(Box.createVerticalStrut(5));
            p.add(sMSGB);
            p.add(Box.createVerticalStrut(5));
            frame.getContentPane().add(p);

            //set frame visible
            frame.pack();
            frame.setVisible(true);

            System.out.println("<Client>: opened stream");

            while(sending) {
                while((getMSG = in.readLine()) != null) {
                    System.out.println(getMSG);
                    textArea.append(getMSG + "\n");
                }
            }
        } 
    }       
}   
服务器线程代码:

public类ServerThread扩展线程{
私有套接字=空;
公共服务器线程(套接字){
超级(“服务器线程”);
this.socket=socket;
}
公开募捐{
试一试(
PrintWriter out=新的PrintWriter(socket.getOutputStream(),true);
BufferedReader in=新的BufferedReader(新的InputStreamReader(socket.getInputStream());
) {
System.out.println(“流打开”);
字符串getMSGs;
而((getMSGs=in.readLine())!=null){
out.println(getMSGs);
System.out.println(“接收和发送消息”);
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
}

提前感谢。

非常简单的决定创建一个像列表一样的PrintWriter支架。别忘了为这个系列创建关闭机制!再想想多线程

public class ServerThread extends Thread {
    private final Socket socket;
    private final List<PrintWriter> outs;

    public ServerThread(Socket socket, List<PrintWriter> outs) {
        super("ServerThread");
        this.socket  = socket;
        this.outs = outs;
        System.out.println("Opened outs: " + outs.size());
    }

    private void sendToAll(String msg) throws IOException {
        for(PrintWriter out: outs) {
            out.println(msg);
        }
    }

    public void run() {
        try (
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        ) {
            System.out.println("stream opened");
            outs.add(out);
            String getMSGs;
            while((getMSGs = in.readLine()) != null) {
                System.out.println("msg received and sent " + getMSGs);
                sendToAll(getMSGs);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public类ServerThread扩展线程{
专用终端插座;
私人最终名单;
公共服务器线程(套接字、列表){
超级(“服务器线程”);
this.socket=socket;
这个.outs=outs;
System.out.println(“openouts:+outs.size());
}
私有void sendToAll(字符串msg)引发IOException{
用于(打印输出:输出){
out.println(msg);
}
}
公开募捐{
试一试(
PrintWriter out=新的PrintWriter(socket.getOutputStream(),true);
BufferedReader in=新的BufferedReader(新的InputStreamReader(socket.getInputStream());
) {
System.out.println(“流打开”);
out.添加(out);
字符串getMSGs;
而((getMSGs=in.readLine())!=null){
System.out.println(“接收和发送消息”+getMSGs);
sendToAll(getMSGs);
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
}

如果是一个大项目,最好为消息创建队列

任何列表实现,但最好为每个套接字添加相同的对象<代码>列表输出=新建CopyOnWriteArrayList()。。。新的ServerThread(serverSocket.accept(),outs.start()