【问题标题】:Adding new FDs to fd_Set while blocking on select在阻塞选择时向 fd_Set 添加新的 FD
【发布时间】:2017-07-18 23:48:57
【问题描述】:

我有一个关于向 FDSET 添加新套接字文件描述符的问题。假设我们已经连接到一个套接字 s1:

fd_set readfds;

//s1 = socket(...);
//connect(s1, ...)...

FD_ZERO(&readfds);
FD_SET(s1, &readfds);

我们通过在线程中调用 select 来等待数据通过套接字:

socket_reader_thread() {

   for (;;)
   {
      int rv = select(n, &readfds, NULL, NULL, &tv);

      if (rv == -1) {
         perror("select"); // error occurred in select()
      }
      else if (rv == 0) {
         printf("Timeout occurred!  No data after 10.5 seconds.\n");
      }
      else {
         // one the descriptors have data
         .....
      }
   }

}

如果我现在想在 readfds 集中添加另一个套接字(或者可能是另外两个套接字等),考虑到 select 是阻塞的,我应该如何继续?如何中断选择

添加零超时并像 poll 一样使用 select 的诀窍是什么?

【问题讨论】:

    标签: c sockets select networking


    【解决方案1】:

    你需要使用“管道技巧”。

    这是创建额外套接字或管道的地方,将其添加到 fd_set。

    然后要中断一个正在运行或挂起的选择,通过另一个线程向它发送一个 1 字节的消息。

    然后选择将返回,如果特殊管道 FD 是集合中准备好的其中之一,这意味着您需要说查看列表或“做工作” - 比如将任何新的 FD 添加到fd_set 在返回到 select 调用之前。

    【讨论】:

      【解决方案2】:

      您可以通过向您的进程发送(和捕获)信号来中断选择,例如使用raise。在这种情况下,select 将返回 -1 并且 errno 设置为 EINTR。然后,您可以更改要等待的事件并再次致电select

      添加零超时并像 poll 一样使用 select 的诀窍是什么?

      可以简单地使用0 的超时时间,在这种情况下,它只会进行非阻塞检查是否触发了任何事件,即轮询。但这应该只在少数情况下完成,因为忙轮询而不是阻塞等待会使用大量机器资源。我什至会考虑中断一个阻塞select 一个有问题的设计,尽管可能没有繁忙的轮询那么糟糕。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-28
        • 1970-01-01
        • 2017-07-19
        相关资源
        最近更新 更多