关于select()的问题

时间:2019-02-01 02:24:26

标签: sockets select tcp server

考虑以下类方法:

void TCPServer::listenWithTimeout() {
  fd_set descrSet;
  struct timeval timeout = {1, 0};
  while (listeningThread.active) {
    std::cout << "TCP Server thread is listening..." << std::endl;
    FD_ZERO(&descrSet);
    FD_SET(mySocketFD, &descrSet);
    int descrAmount = select(mySocketFD + 1, &descrSet, NULL, NULL, &timeout);
    if (descrAmount > 0) {
      assert(FD_ISSET(mySocketFD, &descrSet));
      int threadIndx = findAvailableThread();
      if (threadIndx < 0) {
        std::cout << "Connection not accepted: no threads available..." << std::endl;
      } else {
        joinThread(threadIndx);
        int newSocketFD = accept(mySocketFD, (struct sockaddr *) &mySocket, &clieAddrssLen);
        std::cout << "TCP Client connected..." << std::endl;
        connectionThreads[threadIndx].thread = std::thread(TCPServer::startTCPConnectionWithException, std::ref(*this), threadIndx, newSocketFD);
        connectionThreads[threadIndx].active = true;
      }
    }
  }
  std::cout << "TCP Server thread is terminating..." << std::endl;
}

以下是一些问题:

  1. 当没有可用线程时(findAvailableThreads()返回-1),select()不等待超时是正常行为,因此{{1} }循环真正快速迭代,直到有新线程可用?

  2. 如果是,我如何避免这些真正快速的迭代?除了在while分支内的第13行使用简单的sleep()之外,还有没有办法让if恢复其超时?甚至没有办法完全拒绝传入的连接挂起?

1 个答案:

答案 0 :(得分:2)

  

当没有可用线程时(findAvailableThreads()返回-1),select()不等待其超时是正常行为,因此while循环真正快速迭代直到有新线程可用?

是的,因为在这种情况下,您不会调用accept(),所以您不会更改侦听套接字的状态。只要它具有等待accept()建立的客户端连接,它将保持可读状态。

  

如果是,我如何避免这些真正快速的迭代?

在检查可用线程之前调用accept()。如果没有可用的线程,请关闭接受的连接。

  

不是在if分支中的第13行使用简单的sleep()之类的方法,而是有办法让select()恢复其超时时间吗?

唯一的方法是accept()使侦听套接字进入可读状态的连接,因此它有机会回到不可读状态。在套接字不再处于可读状态之前,超时将不再适用。

  

甚至,是否有一种方法可以完全拒绝待处理的传入连接?

唯一的方法是先accept(),然后根据需要close()

尝试一下:

void TCPServer::listenWithTimeout() {
    fd_set descrSet;
    while (listeningThread.active) {
        std::cout << "TCP Server thread is listening..." << std::endl;
        FD_ZERO(&descrSet);
        FD_SET(mySocketFD, &descrSet);
        struct timeval timeout = {1, 0};
        int descrAmount = select(mySocketFD + 1, &descrSet, NULL, NULL, &timeout);
        if (descrAmount > 0) {
            assert(FD_ISSET(mySocketFD, &descrSet));
            int newSocketFD = accept(mySocketFD, (struct sockaddr *) &mySocket, &clieAddrssLen);
            if (newSocketFD != -1) {
                int threadIndx = findAvailableThread();
                if (threadIndx < 0) {
                    close(newSocketFD);
                    std::cout << "Connection not accepted: no threads available..." << std::endl;
                } else {
                    joinThread(threadIndx);
                    std::cout << "TCP Client connected..." << std::endl;
                    connectionThreads[threadIndx].thread = std::thread(TCPServer::startTCPConnectionWithException, std::ref(*this), threadIndx, newSocketFD);
                    connectionThreads[threadIndx].active = true;
                }
            }
        }
    }
    std::cout << "TCP Server thread is terminating..." << std::endl;
}