select() 如何修改其输入集? [已关闭]

问题描述 投票:0回答:2

我知道 select 在返回时修改输入集。但如何呢? 输入集中的 fd 如何变得不在输入集中?在我看来,只要 fd 一开始就在输入集中,fd_isset(fd) 就会返回 true。那么 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 有什么意义?那么,select() 改变了什么?

来自手册页:

“退出时,这些集合会被就地修改以指示哪些文件描述符实际更改了状态。”

但是关于该系列的哪些方面进行了修改的详细信息明显缺失。

编辑: 针对答案: 那么以下是正确的使用方法吗?

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));
    }
}
c sockets network-programming posix-select
2个回答
3
投票

输入时,

fd_set
告诉
select()
应该检查哪些 FD。
select
制作此列表的副本以供内部使用。当它返回时,它会修改输入结构以包含返回的信息。它可以修改
fd_count
fd_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
    }
}

2
投票

select()
函数将指针指向其参数中的各种文件描述符集。它可以通过这些指针修改 FD 集,就像任何函数可以修改传递给它的任何指针的指示对象一样。鉴于您提供的
fd_set
定义,它可能会通过写入
fd_array
成员 [更新:] 的适当元素来实现,也可能写入
fd_count
成员。

但请注意,说您提供的结构定义是 the

fd_set
结构是不正确的。假设您从与您相关的头文件中提取了它,因此它是 an
fd_set
结构,但结构定义没有记录,因此它在其他系统上的实现可能有所不同。这就是提供
FD_*()
函数来操作这些结构内容的原因之一。

与您的问题特别相关,您可以在

FD_ISSET()
返回后使用
select()
测试文件描述符集的内容。

© www.soinside.com 2019 - 2024. All rights reserved.