【问题标题】:pselect() not recognizing the socket having any IO activitypselect() 无法识别具有任何 IO 活动的套接字
【发布时间】:2009-02-19 03:26:21
【问题描述】:

以下面的代码 sn-p 为例,创建套接字、侦听和接受新套接字都可以正常工作。非阻塞模式也可以工作,但是 pselect(甚至用 select 替换)没有识别 FDset 上准备好的任何 IO 请求。所以返回值总是0(超时)。

我想知道在进入 pselect() 之前是否需要进一步设置其他内容,以便它识别 IO 活动。

.....
 // 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;

【问题讨论】:

    标签: c++ c sockets posix


    【解决方案1】:

    你必须在每次调用select()之前重新初始化fdset参数。

    readfdswritefdsexceptfds 中的每一个都是输入/输出参数。返回时,它们已被修改为仅用于 fd,分别是可读、可写或具有某种异常条件的。

    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() 期间到达的传入连接才会检测到。另外,鉴于您没有使用pselect()sigmask 参数,您不妨直接调用select()

    【讨论】:

    • FD_SET的签名是void FD_SET(int fd, fd_set *set);,参数是其他方式。
    • @VL-80 感谢您指出我的错误。我已经适当地编辑了答案。
    【解决方案2】:

    pselect 的第一个参数应该是*this-&gt;m_pSockFD + 1,不是吗?

    【讨论】:

    • 谢谢,我确实更改了,但不幸的是 pselect 的返回值始终为 0。这意味着已达到超时。我玩过这个值,让它越来越大,但没有发现任何区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 2012-09-20
    • 2017-08-27
    • 1970-01-01
    • 2015-12-06
    相关资源
    最近更新 更多