我有一个问题,我真的不知道如何解决。我有一个多路复用多个连接的程序。这些连接同时接收流数据。我必须配置非阻塞套接字,因为流具有不同的比特率。现在我实际上所做的是将这些套接字保存在一个数组中,循环遍历它们,并使用 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!!!
仍然非常感谢那些试图提供帮助的人!我很欣赏它=)