我有一个问题,我真的不知道如何解决。我有一个多路复用多个连接的程序。这些连接正在同时接收流数据。我必须配置非阻塞套接字,因为流具有不同的比特率。现在我真正做的是将这些套接字保存在一个循环遍历它们的数组中,然后使用select检测是否有数据要读取,并且如果没有,则会对数组中的下一个元素进行处理。 它工作得很好,除了teh CPU总是100%。实际上,如果在某些时候没有任何东西可以从任何套接字读取它仍然会循环。我真的不知道在任何套接字上没有数据可用时如何阻止循环,只有在有数据时才继续运行。我认为这可能是解决方案,但我真的不知道如何做到这一点。该程序必须非常敏感,因为它是一个UDP流记录器,如果它阻塞太长时间,这将在文件中产生滞后。
我非常感谢你。
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超时,从而导致下一次循环到达select函数的问题,给出超时选择是0 !!!
非常感谢那些试图帮助的人!我apreciate它=)
答案 0 :(得分:4)
select
来电的超时时间可以是NULL
,这意味着要永远等待。
答案 1 :(得分:0)
在检查完所有流后,在循环结束时放弃CPU,也可以使用sleep
。这样,您就不会依赖单个流在不久的将来某个时间传输数据,而存在不为其他流提供服务的风险。