【问题标题】:Java how to make server send a message to every client connectedJava如何使服务器向连接的每个客户端发送消息
【发布时间】:2019-08-29 18:49:15
【问题描述】:

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

客户端代码:


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 class Server {

    public static void main(String[] args) {
        boolean listening = true;
        try (ServerSocket serverSocket = new ServerSocket(1010)) {
            while(listening) {
                new ServerThread(serverSocket.accept()).start();
                System.out.println("opened thread");
            }

        } catch(IOException e) {
            e.printStackTrace();
        }

    }
}

服务器线程代码:

public class ServerThread extends Thread {

    private Socket socket = null;

    public ServerThread(Socket socket) {
        super("ServerThread");
        this.socket  = socket;
    }

    public void run() {
        try (
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        ) {
            System.out.println("stream opened");
            String getMSGs;

            while((getMSGs = in.readLine()) != null) {
                out.println(getMSGs);
                System.out.println("msg received and sent");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}

提前致谢。

【问题讨论】:

    标签: java networking chat


    【解决方案1】:

    非常简单的决定创建一个像列表一样的 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();
            }
        }
    }
    

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

    【讨论】:

    • 任何 List 实现,但更好new CopyOnWriteArrayList&lt;PrintWriter&gt;()
    • 您需要为每个套接字添加相同的对象。 List&lt;PrintWriter&gt; outs = new CopyOnWriteArrayList&lt;PrintWriter&gt;(); ... new ServerThread(serverSocket.accept(), outs).start();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 2011-11-28
    • 2013-08-13
    • 2015-08-08
    相关资源
    最近更新 更多