首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么选择report文件描述符总是准备就绪?

为什么选择report文件描述符总是准备就绪?
EN

Stack Overflow用户
提问于 2015-07-05 16:51:43
回答 1查看 71关注 0票数 0

为了测试select系统调用,我编写了一个程序从客户端接收数据:

代码语言:javascript
复制
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>

#define BACKLOG 5

int main(int argc, char *argv[])
{
    if (argc <= 2)
    {
        printf("Usage: %s ip_address port_number\r\n", basename(argv[0]));
        return 1;
    }
    const char *ip = argv[1];
    int port = atoi(argv[2]);

    int ret = 0;
    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &address.sin_addr);
    address.sin_port = htons(port);

    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(listenfd != -1);
    ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
    assert(ret != -1);
    ret = listen(listenfd, BACKLOG);
    assert(ret != -1);

    struct sockaddr_in client_address;
    socklen_t client_addrlen = sizeof(client_address);
    int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlen);
    if (connfd < 0)
    {
        printf("accept failed! errno is %d\r\n", errno);
        close(listenfd);
    }
    else
    {
        printf("accept success!\r\n");
    }

    char buf[1024];
    fd_set read_fds;
    fd_set exception_fds;
    FD_ZERO(&read_fds); 
    FD_ZERO(&exception_fds);

    while (1)
    {
        memset(buf, 0, sizeof(buf));
        FD_ZERO(&read_fds);
        FD_ZERO(&exception_fds);
        FD_SET(connfd, &read_fds);
        FD_SET(connfd, &exception_fds);
        ret = select(connfd + 1, &read_fds, 0, &exception_fds, NULL);
        if (ret < 0)
        {
            printf("selection failed!\r\n");
            break;
        }
        if (FD_ISSET(connfd, &read_fds))
        {
            ret = recv(connfd, buf, sizeof(buf)-1, 0);
            if (ret < 0)
            {
                break;
            }
            printf("received %d bytes of normal data: %s\r\n", strlen(buf), buf);
        }
        else if (FD_ISSET(connfd, &exception_fds))
        {
            ret = recv(connfd, buf, sizeof(buf)-1, MSG_OOB);
            if (ret < 0)
            {
                break;
            }
            printf("received %d bytes of oob data: %s\r\n", strlen(buf), buf);
        }
    }

    close(connfd);
    close(listenfd);
    return 0; 
}

但是,当我从客户端程序发送数据时,上面的服务器程序打印如下:接受成功!

代码语言:javascript
复制
received 16 bytes of normal data: thisisnormaldata
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data: 
received 0 bytes of normal data:

(无休止的“接收到o字节的正常数据”)

为什么select系统调用报告读取的fds总是准备就绪?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-05 17:42:23

select()报告FD不断准备,因为它是不断准备的。它不会阻挡(我猜)。

根据recv()文档的摘录,考虑不断打印的消息的含义

成功完成后,recv()将返回消息的长度(以字节为单位)。如果没有消息可供接收,且对等方已执行有序关闭,recv()应返回0。

由于您使用的是流套接字,它确实可以判断另一端何时执行了有序关闭。你的节目告诉你这就是发生的事。它愿意像你要求的那样告诉你很多次。对于您的程序来说,一个比反复询问更典型的响应是关闭连接的本地端并转移到其他事情上(比如处理其他连接)。

您可能想要select() listenfd文件描述符,以等待后续的连接,不过我看不出这对您有什么好处,因为此时您没有任何其他工作要做,因此只执行阻塞accept()将是一个问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31232749

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档