【问题标题】:How does select() modify its input sets? [closed]select() 如何修改其输入集? [关闭]
【发布时间】:2016-03-03 01:23:43
【问题描述】:

我知道 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 有什么意义?那么,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...
  • “哪些文件描述符实际上改变了状态”对我来说非常清楚。为什么要修改计数?
  • 除了缺少& 之外,您在更新中插入的代码似乎是使用select() 的有效方式。它是否真的有效取决于该代码出现的上下文的许多细节。
  • @JohnBollinger:代码出现的上下文如下:stackoverflow.com/questions/35762852/…

标签: c sockets select network-programming


【解决方案1】:

在输入时,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
    }
}

【讨论】:

  • 谢谢,我编辑了我的问题。
  • select 通话中,您在writeset 之前缺少&。但否则它是正确的。
  • 谢谢。我将在这里链接我的完整代码。 stackoverflow.com/questions/35762852/…
【解决方案2】:

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

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

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

【讨论】:

  • 非常感谢。这很有帮助。
  • 具体来说,它看起来像 Windows 中的 fd_set 结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 2012-08-18
  • 2017-10-05
  • 1970-01-01
相关资源
最近更新 更多