在阻止select

时间:2017-02-28 06:10:45

标签: c sockets select networking

我有一个关于向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是阻塞的,我该怎么办?我怎样才能中断选择

是否添加零超时并使用select如poll?

2 个答案:

答案 0 :(得分:4)

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

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

然后,为了中断正在运行或待处理的选择,通过另一个线程向它发送一个1字节的消息。

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

答案 1 :(得分:2)

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

  

是否添加零超时并使用select如poll?

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