如何仅从select()的fd_set结果中循环活动文件描述符?

kam*_*iro 6 c posix pipe

所以在我目前的服务器实现中,它目前是这样的:

  void loop(){
     // step 1: clear set

     fd_set readfds;

     while(true){

        // step 1:
        FD_ZERO(readfds);

        // step 2:
        loop_through_sockets_and_add_active_sockets_to(theset);

        // step 3:
        switch(select(FD_SETSIZE, &readfds, 0, 0, &tv)) {
           case SOCKET_ERROR:
              patia->receiveEvent(Error, net::getError());
              return;
           case 0:
              return;
        }

        // step 4:
        loop through sockets and check, using FD_ISSET, 
        which read fd's have incoming data.

     }
  }
Run Code Online (Sandbox Code Playgroud)

现在,不清除fd_set(仅在添加/删除通道时使用FD_SET,FD_CLR)将是更好的方法.

我的问题是,如何在select()之后循环遍历fd_set,而不使用FD_ISSET来检查集合中的每个成员是否是集合的一部分?

我的意思是,当你有4000个活动连接时,无论何时有传入数据,上面的循环都必须经过4000个套接字的潜力才能到达正确的连接.如果所有线程都很活跃,那么复杂性将是n ^ 2!

Jer*_*myP 6

我的问题是,如何在select()之后循环遍历fd_set,而不使用FD_ISSET来检查集合中的每个成员是否是集合的一部分?

你不能.

稍微优化会select()返回准备好的描述符的数量,因此,如果您保留已处理的数字的计数,则可以在知道已完成所有操作时停止,而无需到达集合的末尾.

我的意思是,当你有4000个活动连接时,无论何时有传入数据,上面的循环都必须经过4000个套接字的潜力才能到达正确的连接.如果所有线程都很活跃,那么复杂性将是n ^ 2!

我没看到你从哪里得到O(n ^ 2).当然,在select()你回来之后,你必须在途中处理每个准备好的描述符.如果你有4,000个就绪IO描述符,那么在内存C对象中循环遍历4,000个数组的开销将是相当微不足道的.