select()如何修改其输入集?

时间:2016-03-03 01:23:44

标签: c sockets select network-programming

我知道select会在返回时修改输入集。但是怎么样? 输入集中的fd如何不在输入集中? fd_isset(fd)将返回true,在我看来,只要fd在开头的输入集中。那么select()究竟是如何修改其输入集的呢?

这是fd_set结构:

typedef struct fd_set {
  u_int  fd_count;
  SOCKET fd_array[FD_SETSIZE];
} fd_set;

那么select()会更新哪些字段?我们仍然想跟踪所有的fd,所以我不知道select()改变fd_count或fd_array是否有意义?那么,什么选择()改变?

从手册页:

"退出时,会对这些集进行修改,以指示哪些文件描述符实际上已更改状态。"

但是关于这些集合的哪些方面被修改的细节明显缺失。

编辑: 回答答案: 以下是正确的使用方法吗?

while (not error and not socket closes){
    FD_ZERO(&readSet);
    FD_ZERO(&writeSet);
    FD_SET(fd, &readSet);
    FD_SET(socket_num, &readSet);
    FD_SET(fd, &writeSet);
    FD_SET(socket_num, &writeSet);
    select(nfds, &readSet, writeSet, NULL, NULL);
    if(FD_ISSET(fd, &readSet)){
      read(fd, buf, sizeof(buf));
      write(socket_num, buf, sizeof(buf));
      /*memset(buf, 0, sizeof(buf));*/
    }
    if(FD_ISSET(socket_num, &readSet)){
      read(socket_num, buf, sizeof(buf));
      write(fd, buf, sizeof(buf));
    }
}

2 个答案:

答案 0 :(得分:2)

select()函数将指针带到其参数中的各种文件描述符集。它可以通过这些指针修改FD集,其方式与任何函数可以修改传递给它的任何指针的指示对象的方式相同。根据您提供的fd_set定义,可能会写入fd_array成员 [update:]的相应元素,也可能写入fd_count成员。

但请注意,您提供的结构定义是 fd_set结构是不正确的。大概是你从与你相关的头文件中提取它,所以它是 fd_set结构,但结构定义没有记录,所以它可能在其他系统上实现不同。这就是提供FD_*()函数来操纵这些结构内容的一个原因。

与您的问题特别相关,您可以在FD_ISSET()返回后使用select()来测试文件描述符集的内容。

答案 1 :(得分:2)

在输入时,fd_set告诉select()应该检查哪些FD。 select制作此列表的副本供其内部使用。返回时,它会修改输入结构以包含返回的信息。它可以修改fd_countfd_array

这就是为什么使用select()的循环通常会在循环之前保存fd_set的副本,并将其复制回select()调用中使用的变量每次循环,例如

FD_SET(sockfd, &fd_set_init);
while(true) {
    FD_COPY(&fd_set_init, &fd_set);
    n = select(nfds, &fd_set, NULL, NULL, NULL);
    if (n > 0) {
        // Use fd_set here
    }
}