Вопросы по выбору () - PullRequest
       23

Вопросы по выбору ()

0 голосов
/ 01 февраля 2019

Учитывая следующий метод класса:

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() не ожидает своего тайм-аута, и поэтому цикл while выполняет итерацию очень быстро, пока не станет доступен новый поток?

  2. если да, как можноЯ избегаю этих действительно быстрых итераций?Вместо использования что-то вроде простого sleep() в строке 13 внутри ветви if, есть ли способ позволить select() восстановить свое время ожидания?Или даже, есть ли способ полностью отклонить ожидающее входящее соединение?

1 Ответ

0 голосов
/ 01 февраля 2019

когда нет доступных потоков (findAvailableThreads () возвращает -1), является ли нормальное поведение, что select () не ожидает своего тайм-аута, и поэтому цикл while итерация выполняется очень быстро, пока не станет доступен новый поток?

Да, потому что при этом условии вы не вызываете accept(), поэтому вы не меняете состояние прослушивающего сокета.Он останется в читаемом состоянии, пока у него есть клиентское соединение, ожидающее accept() 'ed.

, если да, как я могу избежать этих действительно быстрых итераций?

Позвоните accept(), прежде чем проверять наличие доступного потока.Если поток недоступен, закройте принятое соединение.

Вместо использования что-то вроде простого sleep () в строке 13, внутри ветви if, есть ли способ позволить 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;
}
...