【发布时间】:2013-01-07 06:35:45
【问题描述】:
我是套接字编程的新手,我正在尝试彻底了解它是如何工作的,但现在我真的坚持select()。
问题在于,在我的代码中,在 select 检测到活动并且 fd 保持设置后,似乎在下一次迭代中 FD_ISSET 将自动返回 true,就像它会忽略 select 函数一样。这个问题似乎与这个相同,但我做了我在那里找到的所有事情,但无济于事:http://compgroups.net/comp.unix.programmer/how-does-fd_isset-return-0-after-returne/55058
我确保在 select() 之后重新初始化 timeval 变量,因为我在 Linux 上,并且我理解此函数在不同操作系统上的行为不同,我还在选择之前使用 FD_ZERO 和 FD_SET 重新初始化了 fd 集。
我做错了什么?代码如下:
#include <stdio.h>
#include <strings.h>
#include <sys/select.h>
#include <sys/time.h>
int main () {
struct timeval tv;
tv.tv_sec = 5; // 5 seconds timeout
tv.tv_usec = 0;
fd_set afds, rfds;
FD_ZERO(&afds);
FD_SET(0, &afds);
while (1) {
rfds = afds;
select(1, &rfds, NULL, NULL, &tv);
// linux, reinitialize tv?
tv.tv_sec = 5;
tv.tv_usec = 0;
// so at this point after select runs the first time and detects STDIN activity
// it will enter an infinite loop printing "fd 0 is set" (why?)
if (FD_ISSET(0, &rfds)) {
printf("fd 0 is set\n");
FD_CLR(0, &rfds);
} else {
printf("fd 0 is NOT set\n");
}
}
}
问题编辑,因为我是新用户,无法回答:
事实是我在选择之前初始化 rfds,当它被分配 afds 的值时,它又总是用 FD_ZERO(&afds); 设置。 FD_SET(0, &afds);这对我仍然不起作用。
这是我的理解:
我将标准输入文件描述符添加到 afds
进入while无限循环,rfds = afds(循环开始时rfds永远是= afds)
另外,此时 FD_ISSET(0, &rfds) 将始终为 != 0
select 有 5 秒的超时,所以此时如果我在 5 秒过去之前没有输入任何内容,它就会退出,UNSETTING FD_ISSET(0, &rfds) - 是对吗?因此,如果没有输入任何内容,select 实际上会取消设置 fd 0。这似乎工作正常
当我在超时之前 键入内容时,问题就出现了。此时 FD_ISSET(0, &rfds) 返回 != 0,打印 fd 0 已设置,然后每个循环 fd 都会被设置
好的,这是准确的吗,我猜对了吗?所以实际上 select 不会等待时间过去,因为它实际上检测到 fd 已准备好并退出,设置 fd != 0 ?
这需要进一步的问题:如果我需要服务器每隔一段时间自动向多个客户端发送消息(独立于它从客户端读取的内容),是否可以通过 select 和 gettimeofday 来做到这一点改编上面的代码?
感谢您的帮助。
【问题讨论】: