pselect () не распознает сокет с какой-либо активностью ввода-вывода - PullRequest
1 голос
/ 19 февраля 2009

возьмите, например, следующий фрагмент кода, создание сокета, прослушивание и принятие нового сокета работает нормально. Неблокирующий режим также работает, однако pselect (или даже замена на select) не распознает никаких запросов ввода-вывода, готовых на FDset. поэтому возвращаемое значение всегда равно 0 (время ожидания истекло).

Мне было интересно, нужно ли мне устанавливать что-то еще перед тем, как перейти к pselect (), чтобы он распознавал активность ввода-вывода.

.....
 // Create the socket
        *m_pSockFD = socket(AF_INET, SOCK_STREAM, 0);
        if( *this->m_pSockFD == -1 ){
            throw ....
        }

        // Set the socket address information
        m_pSockAddr->sin_family = AF_INET;
        m_pSockAddr->sin_port =  htons( 6001 );
        m_pSockAddr->sin_addr.s_addr = INADDR_ANY;

        if( bind(*m_pSockFD, (struct sockaddr *) m_pSockAddr, sizeof(*m_pSockAddr) ) != 0 ){
                .....
        }

        // Listen on this socket using a block queue of 5 - default Block Size
        if( listen( *m_pSockFD, 5) != 0 )
                ........


        // change function control to non blocking file descritor for I/O operations
        long fcntlArg;
        if( (fcntlArg = fcntl( *m_pSockFD, F_GETFL, NULL ) ) < 0 ){
               ...........
        }

        fcntlArg |= O_NONBLOCK;
        if( fcntl( *m_pSockFD, F_SETFL, fcntlArg ) <0 ){
              ...........
        }

        //.........

        int newFD = -1;
        socklen_t salen = sizeof(*m_pSockAddr);


        // loop selecting for a I/O operation ready on the file descriptor then go into accept mode
        struct timespec timeOut;
        timeOut.tv_sec = 1;
        timeOut.tv_nsec = 0;

        fd_set fdset;
        FD_SET( *this->m_pSockFD, &fdset );

        while( !m_bShutDownFinished ){

            // TODO pselect is not registering the activity on the socket
            if( pselect( *this->m_pSockFD, &fdset, NULL , NULL , &timeOut,  NULL ) > 0 ){
                cout << "hello client" << endl;
                break;
            }

            // re-initialize the time struct
            timeOut.tv_sec = 1;
            timeOut.tv_nsec = 0;
        }


        // application is shutting down do not try to accept a new socket
        if( m_bShutDownFinished ) return -1;

        newFD = accept(*m_pSockFD, (struct sockaddr *) m_pSockAddr, &salen);
        if( newFD > -1 ){
            ................
        }

        return newFD;

Ответы [ 2 ]

4 голосов
/ 19 февраля 2009

Вы должны заново инициализировать параметры fdset перед каждым вызовом select().

Каждый из readfds, writefds и exceptfds является параметрами ввода / вывода. По возвращении они были изменены, чтобы иметь только те для fds, которые, соответственно, доступны для чтения, записи или имеют какое-то исключительное условие.

for (;;) {
    fd_set rfds;
    FD_ZERO(&rfds);
    FD_SET(sock, &rfds);
    /* code to set up timeout omitted */
    n = select(sock + 1, &rfds, 0, 0, &timeout);
    /* check n, and if sock is present in rfds */
}

Как вы написали код, вы будете обнаруживать входящее соединение только в том случае, если оно будет получено во время самого первого вызова pselect(). Кроме того, учитывая, что вы не используете аргумент sigmask для pselect(), вы можете просто позвонить select().

0 голосов
/ 19 февраля 2009

Первый аргумент pselect должен быть *this->m_pSockFD + 1, не так ли?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...