select()是否可以为没有数据排队的套接字返回就绪状态?

时间:2018-09-21 14:23:05

标签: c networking server posix

我正在阅读R.Stevens的《 UNIX网络编程》,下面的代码片段仅包含相关部分。这是一个回显服务器。

fd_set rset, allset;
int nready, client[FD_SETSIZE];
...
for( ; ; ) {
    rset = allset;
    nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
    ....
    for( i = 0; i <= maxi; i++){
        if ( (sockfd = client[i]) <= 0)
            continue;
        if (FD_ISSET(sockfd, &rset)){
            if( (n = read(sockfd, buf, MAXLINE)) == 0){
                close(sockfd);
                FD_CLEAR(sockfd, &allset);
                client[i] = -1;
            } else
                writen(sockfd, buf, n);
            ...
            }
        }

我将简要描述变量:client是一个数组,其中包含分配给已连接客户端的文件描述符; -1表示自由条目。 nready是可供读取的 fd 的数量。 rset是一种保留位的结构,用于指定准备就绪的 fd allset是相同类型的结构,表示必须由select()测试的 fd

内部for循环检查来自每个已连接客户端的传入数据(这通过FD_ISSSET宏进行了测试)。如果有任何待处理的数据,服务器会将其写回到客户端。如果read()返回0,则表示客户端已向服务器发送FIN,因此它将终止与close()的连接。

现在是问题:作者说我刚才展示的服务器有问题。确实,考虑一个恶意客户端连接到服务器,发送一个字节的数据(而不是换行符),然后进入睡眠状态。服务器将调用read(),读取该字节,然后在下一次对read()的调用中阻塞,等待来自此客户端的更多数据,从而拒绝为所有其他客户端提供服务。我不明白为什么服务器应该在下一次对read()的调用中阻塞:在下一次对read()的调用之前,select()将为每个连接的套接字返回就绪状态,并且客户端没有发送更多数据(该字节已被占用),该客户端的就绪状态位未设置。因此,不会输入客户端的if块,也不会调用read()。很好,除非select()可以为没有数据排队的套接字返回就绪状态,我认为这是不可能的。那我在哪里错了?

0 个答案:

没有答案