2

我有一个问题,我真的不知道如何解决。我有一个多路复用多个连接的程序。这些连接同时接收流数据。我必须配置非阻塞套接字,因为流具有不同的比特率。现在我实际上所做的是将这些套接字保存在一个数组中,循环遍历它们,并使用 select 检测是否有数据要读取,如果没有则继续处理数组中的下一个元素。它工作得很好,除了 CPU 总是 100% 的事实。实际上,如果在某个时候没有任何内容可以从任何套接字读取,它仍然会循环。我真的不知道如何在任何套接字上没有可用数据时阻塞循环,并在有数据时继续运行。我认为这可能是解决方案,但我真的不知道我该怎么做。

我非常感谢你。

PS.:仅供参考,我仍在学习,所以即使解决方案可能很明显,也请不要怪我。


编辑:

这是一些伪代码:

当录制请求进来时,我创建一个新连接并连接到流地址。如果成功,我使用以下函数构建我的 fdset:

build_fdset()
{
    int ii;
    /* */
    FD_ZERO(&fdset);
    /* */
    for (ii = 0; ii < max; ii++)
    {
        if (astRecorder[ii].bUsed != FALSE && astRecorder[ii].socket != INVALID_SOCKET)
        {
            FD_SET(astRecorder[ii].socket,&fdset);
            /* */
            if (astRecorder[ii].socket > maxSocket)
                maxSocket = astRecorder[ii].socket;
        }
    }
}

然后循环处理连接:

main_loop()
{
    struct timeval timeout;
    /* */
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    /* */
    for (;;)
    {   
        memcpy(&fdset_cpy,&fdset,sizeof(fdset));

        int ret = select((maxSocket + 1) , &fdset_cpy, NULL, NULL, &timeout);

        if (iSelectRet <= 0)
            continue;
        else
        {
            int ii;

            for(ii = 0; ii < max; ii++)
            {
                if ((recorders[ii].bUsed) && (FD_ISSET(recorders[ii].socket, &fdset_cpy)))
                {
                    /* receive from socket */
                    /* handle received data */
                }
            }
        }
    }
}

问题:当我将超时设置为 timeout.tv_sec = 1 timeout.tv_usec = 0 时,一切正常,但我得到 100% 的 CPU 使用率!当我将 NULL 作为超时时,尽管套接字上有数据,但程序会在 select() 上阻塞。


解决方案:

好吧,我终于找到了错误!在上面的代码中,我只在主循环之前设置了一次超时值。那么问题在于,对于 fdset,超时结构是由 select() 函数修改的。所以在第一次正确的超时选择之后,超时结构被select()函数修改并设置为0。这导致0超时,因此问题是下一次循环到达选择函数时,超时给定到选择是0!!!

仍然非常感谢那些试图提供帮助的人!我很欣赏它=)

4

2 回答 2

4

呼叫的超时select可能NULL意味着永远等待。

于 2012-06-08T08:03:49.717 回答
0

您也可以sleep在检查所有流以在循环结束时放弃 CPU 后使用。这样一来,您就不必依赖单个流在不久的将来某个时候获得传入数据,从而冒着无法为其他流提供服务的风险。

于 2012-06-08T10:47:56.310 回答