【问题标题】:problem with connecting multiple clients to a server将多个客户端连接到服务器的问题
【发布时间】:2019-06-29 11:13:54
【问题描述】:

嘿,我正在编写一个带有服务器套接字和多个客户端的简单代码,服务器获取每个客户端的用户名并将它们存储在 hashmap 中。服务器接受套接字客户端,客户端输入用户名,但服务器再次接受相同的套接字客户端,它想要它的用户名,代码在这里停止。我希望它可以为多个客户端工作,而不仅仅是一个。

服务器类:

public class Server implements Serializable{

    // [..]

    public void serverConnect() throws IOException, ClassNotFoundException
    {
        listener = new ServerSocket(9090);

        System.out.println("Server is running...");
        while (true)
        {
            System.out.println("Waiting ...");
            socket=listener.accept();
            for (Socket socket:socketList.keySet())
            {
                if (this.socket==socket)
                {
                checkSocket=false;
                }
            }
            if (checkSocket)
            {
            socketList.put(socket,socketNumber);
            System.out.println("Client is connected");
            inputReader = new InputStreamReader(socket.getInputStream());
            reader = new BufferedReader(inputReader);

            user = reader.readLine();
            Server.userList.add(user);
            socketNumber++;
            }
            checkSocket=true;
            }
    }
}

客户端类:

public class Client {
    public Client() {
    }

    public void clientConnect() throws UnknownHostException, IOException {
        System.out.println("enter your username");
        Scanner scanner = new Scanner(System.in);

        String msg = scanner.nextLine();
        Socket socket = new Socket("localhost", 9090);
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
            writer.println(msg);
    }

}

【问题讨论】:

  • 我不知道谁会浏览你的整个代码帖子,特别是因为你没有为我们隔离问题,但我建议你不要在客户端的 while (true) 循环中重新创建流.之前创建一次,然后在循环中使用它们。
  • 另外,你的服务器不需要为它接受的每个客户端创建一个新线程吗?
  • 只是不关心 serverthread 和 clientthread 他们是为了另一个目的,但我的意思是服务器接受套接字客户端并且客户端输入用户名但服务器再次接受相同的套接字客户端并且它想要它的用户名和代码在这里停止。我希望它适用于多个客户端,而不仅仅是一个。

标签: java server client


【解决方案1】:

原则上你有单线程服务器的工作方式(这意味着它一次只能接受一个客户端连接)。主要问题是您接收连接的方式过于复杂。

您可以通过将客户端连接套接字和读取器移动到本地范围并直接处理套接字来简化您当前的代码。

    public void serverConnect() throws IOException {
        listener = new ServerSocket(9090);
        System.out.println("Server is running...");

        while (true) {
            System.out.println("Waiting ...");
            Socket socket = listener.accept();

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                String user = reader.readLine();
                Server.userList.add(user);
            } catch (IOException ignore) {
            } finally {
                socket.close();  
            }
        }
    }

如您所见,除了读取发送的值之外,您不需要保留套接字。如果您只期望来自客户端的一行数据,您还应该关闭套接字,否则客户端可以通过在达到套接字超时之前不发送任何数据来劫持服务器。

除此之外,您还希望使用 try/catch 块将代码包装在 while 循环内,以防止异常终止服务器。

正如我在开头段落中提到的,这段代码作为一个单线程服务器工作,它一次只能响应一个请求。如果您想接受和处理多个请求,您将需要生成一个新线程来处理响应。我建议您按如下方式构建您的代码,但为了简洁起见,您可以执行以下操作:

    public void serverConnect() throws IOException {
        int MAX_WORKERS = 100;
        ExecutorService service = Executors.newFixedThreadPool(MAX_WORKERS);
        ServerSocket listener = new ServerSocket(9090);

        System.out.println("Server is running...");
        while (true) {
            System.out.println("Waiting ...");
            Socket socket = listener.accept();

            service.submit(() -> {
                System.out.println("Client is connected");
                try {
                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                        String user = reader.readLine();
                        Server.userList.add(user);
                    } finally {
                        socket.close();
                    }
                } catch (Throwable ignore) {
                }
            });
        }
    }

所以上面发生的所有事情是我们正在使用ExecutorService 创建一个包含 100 个线程的线程池。这意味着理论上我们可以接受 100 个并发连接。

当一个连接被接受时,我们将套接字和工作代码提交给一个线程,这意味着主线程可以返回监听新的连接。

【讨论】:

  • 它不起作用。即使是第一个客户端也无法连接到服务器。
  • 1.尝试在客户端代码中使用 127.0.0.1 而不是 localhost。
  • 没有区别。 -
  • 您能否将服务器和客户端代码的输出添加到您的问题中?
猜你喜欢
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 2018-10-05
  • 1970-01-01
相关资源
最近更新 更多