我需要限制可以连接到服务器的客户端数量。 我只希望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;
}
}
}
答案 0 :(得分:1)
仅接受一定数量的客户端并将其余客户端排队的最简单方法是,在达到限制后停止监听客户端。
ServerSocket
已经有一个队列,因此,如果您停止监听,无论如何都会自动对过多的请求进行排队。要控制队列大小,请使用ServerSocket(int port, int backlog)
构造函数:
[...]
用于传入连接指示(连接请求)的最大队列长度设置为backlog参数。如果在队列已满时出现连接指示,则拒绝连接。
[...]
参数:
port-端口号,或0表示使用自动分配的端口号。
backlog-请求的传入连接队列的最大长度。
因此,如果正在运行的客户端线程数已达到限制,请不要调用serverSocket.accept()
。等待客户端线程结束,然后主线程再次调用accept()
。
最简单的管理方法是使用带有给定线程限制的Semaphore
作为许可次数,即主线程在调用{{之前,先调用acquire()
1}},并且客户端线程在结束之前从accept()
块调用release()
。
提示:如果使用线程池而不是为每个请求启动新线程,则可以获得更好的性能。