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 ++选择函数过早中断[重复]的主要内容,如果未能解决你的问题,请参考以下文章

C#实体框架:添加/插入记录并选择他而不保存更改[重复]

打印当前PATH的命令是啥(window`s API,使用c ++)[重复]

将元素放在列表的开头[重复]

excel如何不重复分组

Python编程题35--删除字符串中的所有相邻重复项

如何用excel比对两个档案相同的资料