我试图限制我的服务器使用信号量接受的连接数,但是在运行时,我的代码似乎没有这个限制 - 我是否正确使用信号量?例如。我已将许可证号码硬编码为2,但我可以连接无限数量的客户......
public class EServer implements Runnable {
private ServerSocket serverSocket;
private int numberofConnections = 0;
private Semaphore sem = new Semaphore(2);
private volatile boolean keepProcessing = true;
public EServer(int port)
throws IOException {
serverSocket = new ServerSocket(port);
}
@Override
public void run() {
while (keepProcessing) {
try {
sem.acquire();
Socket socket = serverSocket.accept();
process(socket, getNextConnectionNumber());
} catch (Exception e) {
} finally {
sem.release();
}
}
closeIgnoringException(serverSocket);
}
private synchronized int getNextConnectionNumber() {
return ++numberofConnections;
}
// processing related methods
}
答案 0 :(得分:0)
您的process
方法是什么样的?它可以在你想要它之前返回,因此在你想要它之前释放信号量吗?
答案 1 :(得分:0)
您创建了多少个主题? 1个线程中只有1个服务器实例?或者是2个线程中使用了1个实例?
1个实例/ 1个帖子 - 你的循环正在连续处理, processing 一次接受1个线程。这不是因为信号量,而是因为它只是一个线程。其他连接正在排队等待接受。
1个实例/ 2个线程 - 您的代码(信号量)将您的服务器限制为处理 同时接受 2个连接 ,但TCP / IP允许排队连接(我认为通常的默认队列长度为5)。第三个同步请求(在前两个请求中的任何一个完成处理之前进入的请求)将等待一段时间(我不记得客户端默认等待多长时间)。第4,第5等也是如此。
无论哪种方式:所以你的代码会有无限的连接,因为代码只是限制了接受的数量。一旦接受,连接将保持不变,直到服务器或客户端关闭连接。
更新 - 响应OP评论提供更多信息。
进程与无限循环保持持久连接 - 罗伯特12分钟前
答案 2 :(得分:0)
你需要删除finally块
答案 3 :(得分:-1)
你不应该在你的finally块中调用release。最后总是执行块。您要做的是在异常中释放锁定,或者在客户端断开连接时:
while (keepProcessing) {
try {
sem.acquire();
Socket socket = serverSocket.accept();
process(socket, getNextConnectionNumber());
} catch (Exception e) {
//Here the client hasn't been connected, so release the lock.
sem.release();
} finally {
//code here always executes, exception or not
}
}
然后在客户端代码的适当位置释放锁:
...
//The client is shutting down / disconnecting
serverInstance.sem.release(); //not good OOP
OR
serverInstance.clientFinished(); //callback, where clientFinished in your server class will release the lock
...
当然,根据代码的组织方式,有多种方法可以释放锁定,但关键是当你在finally块中调用release时,它将始终执行(使许可可用于下一个传入连接)。因此,只有当存在异常(您知道尚未建立连接)或b)客户端(可能通过服务器上的某种回调/侦听器)时才释放a)在服务器中,当您知道连接是完成/断开/以其他方式终止。
答案 4 :(得分:-1)
信号量不会限制与服务器的连接数。
信号量限制访问特定代码段的线程数。问题,您的服务器将接受所做的传入套接字请求,但每个套接字线程将阻塞信号量。
此外,您的run
方法包含一个获取和释放信号量的循环,这会导致所有套接字在信号量上循环。
要查看此操作,请添加一些日志语句。一个在获取信号量之前,一个在获取信号量之后立即获得信号量,另一个信号在发布之前,另一个在发布之后立即获得信号量。
那么如何限制与服务器的连接?
检查backlog
ServerSocket
构造函数参数
public EServer (int port)
throws IOException
{
// 'backlog' is in fact a listening queue length.
// if more than 2 socket requests are made at a time,
// they are refused. probably want to parameterize
// this :)
serverSocket = new ServerSocket (port, 2);
}