限制可以同时连接到服务器的客户端数量

时间:2019-05-09 15:47:18

标签: java multithreading server client chatroom

我需要限制可以连接到服务器的客户端数量。 我只希望5个客户端能够连接。 当第六个客户端尝试连接时,他将被添加到队列中。 一旦其中一个客户端离开,将调用.remove,它将进入队列并获取等待的第一个客户端,并将其连接到聊天。

    public void start() {
    keepGoing = true;
    /* create socket server and wait for connection requests */
    try 
    {
        // the socket used by the server
        ServerSocket serverSocket = new ServerSocket(port);

        // infinite loop to wait for connections
        while(keepGoing) 
        {
            // format message saying we are waiting
            display("Server waiting for Clients on port " + port + ".");

            Socket socket = serverSocket.accept();      // accept connection
            // if I was asked to stop
            if(!keepGoing)
                break;
            ClientThread t = new ClientThread(socket);  // make a thread of it
            al.add(t);                                  // save it in the ArrayList
            t.start();
        }
        // I was asked to stop
        try {
            serverSocket.close();
            for(int i = 0; i < al.size(); ++i) {
                ClientThread tc = al.get(i);
                try {
                tc.sInput.close();
                tc.sOutput.close();
                tc.socket.close();
                }
                catch(IOException ioE) {
                    // not much I can do
                }
            }
        }
        catch(Exception e) {
            display("Exception closing the server and clients: " + e);
        }
    }
    // something went bad
    catch (IOException e) {
        String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
        display(msg);
    }
}   

向所有客户广播消息:

    private synchronized void broadcast(String message) {
    // add HH:mm:ss and \n to the message
    String time = sdf.format(new Date());
    String messageLf = time + " " + message + "\n";
    // display message on console or GUI
    if(sg == null)
        System.out.print(messageLf);
    else
        sg.appendRoom(messageLf);     // append in the room window

    // we loop in reverse order in case we would have to remove a Client
    // because it has disconnected
    for(int i = al.size(); --i >= 0;) {
        ClientThread ct = al.get(i);
        // try to write to the Client if it fails remove it from the list
        if(!ct.writeMsg(messageLf)) {
            al.remove(i);
            display("Disconnected Client " + ct.username + " removed from list.");
          }
      }
  }

对于使用LOGOUT消息注销的客户:

    synchronized void remove(int id) {
    // scan the array list until we found the Id
    for(int i = 0; i < al.size(); ++i) {
        ClientThread ct = al.get(i);
        // found it
        if(ct.id == id) {
            al.remove(i);
            return;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

仅接受一定数量的客户端并将其余客户端排队的最简单方法是,在达到限制后停止监听客户端。

ServerSocket已经有一个队列,因此,如果您停止监听,无论如何都会自动对过多的请求进行排队。要控制队列大小,请使用ServerSocket(int port, int backlog)构造函数:

  

[...]

     

用于传入连接指示(连接请求)的最大队列长度设置为backlog参数。如果在队列已满时出现连接指示,则拒绝连接。

     

[...]

     

参数:

     

port-端口号,或0表示使用自动分配的端口号。

     

backlog-请求的传入连接队列的最大长度。

因此,如果正在运行的客户端线程数已达到限制,请不要调用serverSocket.accept()。等待客户端线程结束,然后主线程再次调用accept()

最简单的管理方法是使用带有给定线程限制的Semaphore作为许可次数,即主线程在调用{{之前,先调用acquire() 1}},并且客户端线程在结束之前从accept()块调用release()

提示:如果使用线程池而不是为每个请求启动新线程,则可以获得更好的性能。