服务器并发客户端连接数限制及队列接入实现需求
Implement Client Connection Limit with Waiting Queue
Got it, let's break down how to add the connection limit (max 5 concurrent clients) and waiting queue functionality to your existing server code. Here's the step-by-step implementation:
1. Add Required Member Variables
First, add these fields to your server class to track the max connections and hold waiting clients:
// Maximum number of concurrent clients allowed private static final int MAX_CONCURRENT_CLIENTS = 5; // Queue to hold clients waiting for a connection slot private final Queue<Socket> waitingClientQueue = new LinkedList<>();
2. Modify the start() Method to Handle Queueing
Update the connection acceptance logic to check if we've hit the client limit. If yes, add the new client to the queue; otherwise, spin up a ClientThread immediately:
public void start() { keepGoing = true; /* 创建Socket服务器并等待连接请求 */ try { // 服务器使用的Socket ServerSocket serverSocket = new ServerSocket(port); // 循环等待连接 while(keepGoing) { // 输出等待提示信息 display("Server waiting for Clients on port " + port + "."); Socket socket = serverSocket.accept(); // 接受连接 // 若收到停止指令则退出 if(!keepGoing) { socket.close(); // Close the new socket to avoid client hanging break; } synchronized(this) { if(al.size() < MAX_CONCURRENT_CLIENTS) { // Slot available: create and start client thread ClientThread t = new ClientThread(socket); al.add(t); t.start(); display("New client connected. Current active clients: " + al.size()); } else { // No slots left: add to waiting queue waitingClientQueue.add(socket); display("Client added to waiting queue. Queue size: " + waitingClientQueue.size()); // Optional: Notify client they're in queue try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { out.println("Server is full. You're in queue. Position: " + waitingClientQueue.size()); } catch(IOException e) { display("Failed to send queue status to client: " + e); socket.close(); waitingClientQueue.remove(socket); } } } } // 执行停止操作 try { serverSocket.close(); // Close all waiting client sockets while(!waitingClientQueue.isEmpty()) { Socket waitingSocket = waitingClientQueue.poll(); try { waitingSocket.close(); } catch(IOException e) { display("Error closing waiting client socket: " + e); } } 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) { // 无有效处理措施 } } } catch(Exception e) { display("Exception closing the server and clients: " + e); } } // 捕获异常 catch (IOException e) { String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n"; display(msg); } }
3. Update the remove() Method to Process Waiting Clients
When a client disconnects, check the waiting queue and let the next client in:
// 处理客户端通过LOGOUT消息发起的注销 synchronized void remove(int id) { // 遍历ArrayList查找对应ID的客户端 for(int i = 0; i < al.size(); ++i) { ClientThread ct = al.get(i); // 找到目标客户端 if(ct.id == id) { al.remove(i); display("Disconnected Client " + ct.username + " removed from list. Current active clients: " + al.size()); // Check if there are waiting clients to connect if(!waitingClientQueue.isEmpty()) { Socket nextClientSocket = waitingClientQueue.poll(); ClientThread newClientThread = new ClientThread(nextClientSocket); al.add(newClientThread); newClientThread.start(); // Optional: Notify client they're now connected try (PrintWriter out = new PrintWriter(nextClientSocket.getOutputStream(), true)) { out.println("You're now connected to the server!"); } catch(IOException e) { display("Failed to send connection success message: " + e); al.remove(newClientThread); nextClientSocket.close(); } display("Client from queue connected. Current active clients: " + al.size() + ", Queue size: " + waitingClientQueue.size()); } return; } } }
Key Notes & Recommendations
- Thread Safety: We use
synchronized(this)to ensure safe access to the active clients list (al) and waiting queue, since multiple threads (main accept thread, client threads callingremove) will modify these structures. Alternatively, you could use aConcurrentLinkedQueuefor the waiting clients to reduce lock contention. - Client Timeouts: Waiting clients might disconnect unexpectedly. You could add logic to periodically check for closed sockets in the queue and remove them, or set a timeout on the waiting sockets.
- User Feedback: The optional queue status messages help users understand why their connection is delayed, which improves the overall experience.
内容的提问来源于stack exchange,提问作者Pierre Ibrahim
相关产品推荐
相关产品推荐

