好的,首先关闭:对不起,如果之前已经询问过这个问题,但是我无法找到正确的关键字。
情况:我有一个小型网络服务器,它运行在自己的线程中。 ' Run' -Method迭代一组活动套接字(UDP和TCP),检查Activity并做它的事情。所有这些都是通过select
实现的。
有可能,虽然“卡住了”。在select
中添加了一个新服务器。为此,我加入了一个“断路器插座”,与其他插座一起进行检查。添加新套接字时会关闭它,因此还会监视新套接字的流量。 (每次选择被破坏时都会重新生成fd_set)
代码就像这样(缩写):
fd_set fds;
SOCKET mSock = Breaker;
FD_ZERO(&fds);
//Aquire Mutex
if(Breaker == INVALID_SOCKET)
mSock = Breaker = socket(AF_INET, SOCK_STREAM, 0);
FD_SET(Breaker, &fds);
//Iterate over active sockets and add them to fds.
//Release Mutex
if(select(mSock + 1, &fds, NULL, NULL, NULL) > 0) {
//AquireMutex
//Iterate over active sockets, check for activity and act accordingly.
if(Breaker != INVALID_SOCKET && FD_ISSET(Breaker, &fds)
//Close Breaker and set it to INVALID_SOCKET
//Release Mutex
}
现在实际问题是:select
不断被打破,无论我是否关闭Breaker。它不断报告'活动'在插座上。
Breaker是一个简单的套接字,没有绑定或连接。 如果我将Breaker的类型更改为' DGRAM',即使关闭,它也不会中断选择。
语言是C ++,Platform是Linux派生的,INVALID_SOCKET定义为-1,SOCKET是int的typedef。 (代码也适用于WinSock)
感谢您的帮助。
编辑:
我试过从缓冲区读取。在断路器套接字上调用recv
返回-1,将errno
设置为107(传输端点未连接),这并不奇怪,看看它是如何连接的。
编辑: 由于我的意图显然不清楚,我将再次描述它。 有可能在任何给定的时间点将新的服务器套接字添加到队列中。但是,除非select被破坏(并且fd_set随后用新套接字重新填充)至少一次,否则不会监视此套接字的流量。因此丢弃到达新套接字的任何流量。
我知道,我可以使用超时,但我希望它能成为一种不同的解决方案。
答案 0 :(得分:7)
这是预期的。如果没有什么可以等待的,select
就等不及了。如果套接字关闭,则没有什么可以等待的。如果未连接套接字,则无需等待。如果你想让select
等待,你必须给它一些等待的东西。当它告诉你没有什么可以等待时,你不应该让它再等一下 - 这没有任何意义。在你再次打电话之前,你必须处理select
告诉你的任何事情,否则同样的事情会继续发生。
答案 1 :(得分:2)
您可以使用管道(man 2 pipe
)代替使用套接字来发出事件信号。
如果可能的话,我宁愿修改你的架构。
PS:我发誓我没有看过Michael Burr在评论中提出的问题。