C ++选择函数过早中断[重复]
Posted
技术标签:
【中文标题】C ++选择函数过早中断[重复]【英文标题】:C++ select function breaks prematurely [duplicate] 【发布时间】:2014-11-27 07:40:32 【问题描述】:好的,首先:抱歉,如果之前有人问过这个问题,但如果有人问过,我无法找出正确的关键字。
情况:我有一个小型网络服务器,它在它自己的线程中运行。 “运行”方法遍历活动套接字(UDP 和 TCP)的集合,检查活动并完成它。这一切都是通过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++,平台是 Linux 衍生版本,INVALID_SOCKET 定义为 -1,SOCKET 是 int 的 typedef。 (代码应该也可以与 WinSock 一起使用)
感谢您的帮助。
编辑:
我试过从缓冲区读取。在返回 -1 的 Breaker 套接字上调用 recv
,将 errno
设置为 107(未连接传输端点),这并不奇怪,看看它实际上是如何未连接的。
编辑: 由于我的意图显然不清楚,我将再次描述它。 有可能在任何给定时间点将新的服务器套接字添加到队列中。但是,不会监视此套接字的流量,除非 select 被破坏(并且 fd_set 随后用新套接字重新填充)至少一次。因此,任何到达新套接字的流量都会被丢弃。
我知道,我可能会使用超时,但我希望有不同的解决方案。
【问题讨论】:
你想做什么?除了您对这种行为感到惊讶之外,您所说的一切都不令人惊讶。 通过 TCP 连接,您可以选择侦听器套接字来等待新的传入连接。 @PatrickB。是的,确实如此。但是,如果将新的侦听器添加到队列中,就会出现问题。 【参考方案1】:这是意料之中的。如果没有什么可以等待,select
不能等待。如果套接字已关闭,则无需等待。如果套接字未连接,则无需等待。如果你想让select
等待,你必须给它一些等待的东西。当它告诉你没有什么可以等待时,你不应该要求它再次等待——那是没有意义的。在再次调用之前,您必须处理 select
告诉您的任何事情,否则同样的事情会继续发生。
【讨论】:
好的,那么我将如何让这个场景发挥作用呢?我想要的是简单地关闭套接字(或做任何事情)以使选择中断并重新填充 fd_set。 我不关注。如果要关闭套接字,请致电close
。如果您希望select
中断,则安排它在您想要的条件发生时中断。您是否试图在另一个线程使用它时关闭一个线程中的套接字? (那行不通。)还是什么?你没有很好地描述你的问题。
首先:感谢您的帮助。第二:我希望能够在任何给定的时间点中断选择,因此它将用更新的数据重新填充变量“fd_set”(要监听的附加套接字)。如果有比关闭套接字更简单的方法,我还没有找到。
@ATaylor:看看这个 SO 问题是否对您有帮助:***.com/questions/2486727/…
@ATaylor 来自另一个线程?关闭套接字不起作用,不要那样做。但是,当您确定没有其他线程正在或可能正在使用它时,您可以先shutdown
套接字,然后再 close
它。【参考方案2】:
您可以使用管道 (man 2 pipe
),而不是使用套接字来发出事件信号。
如果可能的话,我宁愿修改你的架构。
PS:我发誓我没有看过 Michael Burr 在评论中提出的问题。
【讨论】:
哈哈,是的,结果很重要,而不是来自谁。我马上去看看。 在 Steven 的“Unix Network Programming, Vol 1”第 3 版中也讨论了使用管道允许select()
被中断。 (第 20.5 节)。我认为这是一种相对常见的技术,应该更广为人知。以上是关于C ++选择函数过早中断[重复]的主要内容,如果未能解决你的问题,请参考以下文章