【问题标题】:How to group to 2 clients to send messages [duplicate]如何分组到2个客户端发送消息[重复]
【发布时间】:2020-12-17 18:15:23
【问题描述】:

我想要做的是第 2 组客户并让他们相互交流。因此,如果连接了 2 个客户端,它们将只能相互通信,如果连接了第三个客户端,它将无法与其他 2 个客户端通信,但它会创建另一组 2 个客户端,依此类推......我的下面的代码目前从一个客户端向所有客户端广播一条消息,但我希望它像上面描述的那样工作,并且一直很难找到解决方案。任何帮助表示赞赏。

public class ChatServer {


private static final int PORT = 9001;


private static HashSet<String> names = new HashSet<String>();


private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();

static int clientCounter = 0;


public static void main(String[] args) throws Exception {
    System.out.println("The chat server is running.");
    ServerSocket listener = new ServerSocket(PORT);
    try {
        while (true) {
            new Handler(listener.accept()).start();
        }
    } finally {
        listener.close();
    }
}


private static class Handler extends Thread {
    private String name;
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    
    public Handler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {

            
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            
            while (true) {
                out.println("SUBMITNAME");
                name = in.readLine();
                if (name == null) {
                    return;
                }
                synchronized (names) {
                    if (!names.contains(name)) {
                        names.add(name);
                        break;
                    }
                }
            }

            
            out.println("NAMEACCEPTED");
            
            clientCounter++;
            

            
                if (clientCounter > 0 && clientCounter <= 2) {

                    writers.add(out);

                    
                    while (true) {
                        String input = in.readLine();
                        if (input == null) {
                            return;
                        }

                        for (PrintWriter writer : writers) {
                            writer.println("MESSAGE " + name + ": " + input);
                        }

                    }

                } else {
                    clientCounter = 1;
                }
            
            

            
            
            
        } catch (IOException e) {
            System.out.println(e);
        } finally {
            
            if (name != null) {
                names.remove(name);
            }
            if (out != null) {
                writers.remove(out);
            }
            try {
                socket.close();
            } catch (IOException e) {
            }
        }
    }
}

}

【问题讨论】:

    标签: java networking tcp client-server


    【解决方案1】:

    这是使它工作的一种方法。首先,您需要修改接受连接的循环,以便它跟踪“先前接受的套接字”。当客户端连接时,检查是否有previousSocket:如果没有,则将其当前套接字存储为previousSocket。如果有,那么您现在有两个已连接的客户端,它们可以相互通信:

    Socket previousSocket = null;
    while (true) {
        Socket newSocket = listener.accept();
        if (previousSocket == null) {
            previousSocket = newSocket;
        } else {
            new Handler(previousSocket, newSocket).start();
            new Handler(newSocket, previousSocket).start();
            previousSocket = null;
        }
    }
    

    您需要进行的另一项更改是将“对等点”的概念添加到您的 Handler 类中。对等点是您用来与其他客户端通信的套接字。然后,将向所有客户端发送消息的for 循环替换为仅向对等方发送消息的代码:

    peerOut.println("MESSAGE " + name + ": " + input);
    

    这里有一个更完整的代码示例,用于说明修改后的 Handler 类。为简洁起见,我省略了名称注册和错误处理 - 您需要将其添加回来。

    private static class Handler extends Thread {
        private String name;
        private Socket socket;
        private Socket peerSocket;
        private BufferedReader in;
        private PrintWriter out;
    
        public Handler(Socket socket, Socket peerSocket) {
            this.socket = socket;
            this.peerSocket = peerSocket;
        }
    
        public void run() {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    
            // name registration and error handling omitted for brevity
    
            PrintWriter peerOut = new PrintWriter(peerSocket.getOutputStream(), true);
    
            while (true) {
                String input = in.readLine();
                if (input == null) {
                    return;
                }
    
                // Replaces "for (PrintWriter writer : writers) { ... }"
                peerOut.println("MESSAGE " + name + ": " + input);
            }
        }
    }
    

    【讨论】:

    • 这似乎不起作用不幸的是代码似乎没有向一个客户发送消息。
    • 其实这段代码确实有一些功能,谢谢:)
    • 但是我的代码仍然有问题。这是我似乎无法让他们在彼此之间连续发送消息,而是两个客户端都等待输入,然后才将消息发送给彼此。
    • 这是客户端问题。用客户端代码发布另一个问题
    【解决方案2】:

    我能想到的最简单的解决方案是:

    创建一个扩展线程并将两个套接字作为输入的类

    这个类在运行中所做的就是等待任何东西被写入第一个套接字并将其发送到第二个套接字

    您的主要功能只是等待连接

    当它获得一个连接时,它接受它并保存套接字(我从现在开始将其称为 socketA)但一直等待第二个连接(因为您的聊天程序需要两个客户端)

    一旦第二个连接到来,你就接受它(这将是 socketB)

    它现在从一开始就从你的类中创建两个对象,一个将 socketA 作为第一个,socketB 作为第二个参数,另一个将 socketB 作为第一个,socketA 作为第二个参数

    第一个实例负责从 socketA 向 socketB 发送消息,第二个实例负责从 socketB 向 socketA 发送消息,让我们两个聊天

    您的主服务器现在只需要等待下一个连接并从头开始“重新启动”

    【讨论】:

      猜你喜欢
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 2015-03-23
      • 1970-01-01
      • 2019-11-06
      • 2017-09-02
      相关资源
      最近更新 更多