dea*_*clo 5 c sockets select timeout
while (xxx) {
timeout.tv_sec=TIMEOUT;
timeout.tv_usec=0;
FD_ZERO(&set);
FD_SET(sd,&set);
switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout))
xxxxx
}
Run Code Online (Sandbox Code Playgroud)
然而,工作正常
FD_ZERO(&set);
FD_SET(sd,&set);
while (xxx) {
timeout.tv_sec=TIMEOUT;
timeout.tv_usec=0;
switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout))
xxxxx
}
Run Code Online (Sandbox Code Playgroud)
没有.它第一次工作,但下次它运行while循环时,即使sd套接字接收数据,它也会超时.在我看来,每次都必须清空和填充设置是浪费资源.
任何人都有一个很好的解释为什么这是,甚至更好,也许是一个如何避免它的建议?
DGe*_*try 12
select修改其参数.你真的必须每次都重新初始化它.
如果您担心开销,那么在内核中处理完整FD_SET的成本比FD_ZERO的成本更重要.您只想传递最大fd,而不是FD_SETSZIZE,以最小化内核处理.在你的例子中:
switch (select((sd + 1),&set,NULL,NULL,&timeout))
Run Code Online (Sandbox Code Playgroud)
对于具有多个fds的更复杂的情况,通常最终会维护一个max变量:
FD_SET(sd,&set);
if (sd > max) max = sd;
... repeat many times...
switch (select((max + 1),&set,NULL,NULL,&timeout))
Run Code Online (Sandbox Code Playgroud)
如果你有大量的文件描述符,并且担心将它们包含在内,那么你应该看看select()的一些替代方法.你没有提到你正在使用的操作系统,但对于类Unix操作系统,有一些:
API是不同的,但它们本质上都是一个有状态的内核接口,用于维护一组活动文件描述.将fd添加到集合后,您将收到有关该fd事件的通知,而无需再次将其连续传递.