簡體   English   中英

Java Sockets - 如何將消息發送到多個線程?

[英]Java Sockets - How can I send messages to multiple threads?

我使用 Java 制作了一個聊天應用程序(服務器/客戶端)。 注意:服務器作為自己的 jar 文件運行,每個客戶端作為自己的 jar 文件運行。

每個客戶端都在自己的線程上。

每當我向服務器發送消息時,每個客戶端都會收到消息,但是當我從客戶端發送消息時,只有服務器會收到消息。 當客戶端發送消息時,我希望所有連接的客戶端和服務器都能接收消息,這樣所有客戶端都可以一起通信,也可以與服務器通信。

我看過很多關於這個的帖子和視頻,但大多數都太混亂了,我無法理解。 有人可以幫我理解如何在線程之間發送消息嗎? 謝謝!

-- 我的代碼 --

客戶:

public Client(User user, String address, int port) {

        try {
            socket = new Socket(address, port);

            ClientApplicationUI app = new ClientApplicationUI();

            app.setTitle("Chat Application - " + user.getUsername());
            app.setVisible(true);

            ServerConnection connection = new ServerConnection(socket, app);

            output = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));

            new Thread(connection).start();

            app.getButton().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    if (app.getTextField().getText() != null && app.getTextField().getText().length() > 0) {
                        String message = MessageUtil.getMessage(Message.LOGGER_PREFIX) + " <" + user.getUsername() + "> " + app.getTextField().getText() + "\n";
                        try {
                            output.writeUTF(message);
                            output.flush();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                        }

                }

            });

        } catch (UnknownHostException e) {
            System.out.println(e);
            System.out.println("Could not connect! Reason: " + e);
        } catch (IOException e) {
            System.out.println("Could not connect! Reason: " + e);
        }

    }

服務器連接

public class ServerConnection implements Runnable {

    @SuppressWarnings("unused")
    private Socket socket;
    private DataInputStream in;
    private ClientApplicationUI app;

    public ServerConnection(Socket socket, ClientApplicationUI app) throws IOException {
        this.socket = socket;
        this.app = app;
        in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    }

    @Override
    public void run() {
        while (true) {
            String message;
            try {
                message = in.readUTF();
                app.logMessage(message);
            } catch (IOException e) {

                e.printStackTrace();
            }
        }

    }

}

服務器

public class Server {

    private Socket socket = null;
    private ServerSocket server = null;
    private ExecutorService pool = Executors.newFixedThreadPool(4);

    public Server (int port) {

        try {

            ApplicationUI app = new ApplicationUI();
            app.setVisible(true);
            server = new ServerSocket(port);
            app.logMessage(MessageUtil.getMessage(Message.LOGGER_PREFIX) + " " + MessageUtil.getMessage(Message.INFO) + " Server started!\n");
            app.logMessage(MessageUtil.getMessage(Message.LOGGER_PREFIX) + " " + MessageUtil.getMessage(Message.INFO) + " Waiting for new connections...\n");


            while (true) {
                socket = server.accept();
                ConnectionHandler clientThread = new ConnectionHandler(socket, app);
                app.logMessage(MessageUtil.getMessage(Message.LOGGER_PREFIX) + " " + MessageUtil.getMessage(Message.INFO) + " A new client has been accepted!\n");

                pool.execute(clientThread);
            }


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

        }

    }

    public static void main(String[] args) {
        Server server = new Server(58139);
    }
}

連接處理程序

public class ConnectionHandler implements Runnable {

    private Socket client;
    private ApplicationUI app;
    private DataInputStream in;
    private DataOutputStream out;

    public ConnectionHandler(Socket client, ApplicationUI app) throws IOException {
        this.client = client;
        this.app = app;
        in = new DataInputStream(new BufferedInputStream(client.getInputStream()));
        out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
    }

    @Override
    public void run() {

        try {
        app.getButton().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (app.getTextField().getText() != null && app.getTextField().getText().length() > 0) {
                    String message = MessageUtil.getMessage(Message.LOGGER_PREFIX) + " <Server> " + app.getTextField().getText() + "\n";
                    try {
                        sendMessage(message);

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

            }

        });

        String message = "";
        while (!message.equals("/stop")) {
                message = in.readUTF();
                app.logMessage(message);
        }

    } catch (IOException e) {
        System.err.println("IO exception in connection handler!");
        System.err.println(e.getStackTrace());
    } finally {
        try {
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    }

    private void sendMessage(String message) throws IOException {
        out.writeUTF(message);
        out.flush();

    }       

}

您需要了解 sockets 的工作原理。 它們始終是客戶端和服務器。
有兩種方法可以實現您想要的:

第一個解決方案:
將適用於所有客戶端的消息發送到服務器,並讓服務器將消息分發給所有其他客戶端。 服務器將需要跟蹤已經連接的客戶端,即存儲它們的Socket


第二種解決方案:(這完全是不可取的)
如果您想在不涉及實際服務器的情況下向網絡客戶端發送消息,則需要該客戶端充當服務器,或者反過來。 這意味着每個客戶端實際上都需要監聽所有其他客戶端,而不僅僅是服務器。

您絕對應該使用第一個解決方案 go !

暫無
暫無

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

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