使用 select() 进行非阻塞套接字连接总是返回 1 [英] Using select() for non-blocking sockets to connect always returns 1

查看:47
本文介绍了使用 select() 进行非阻塞套接字连接总是返回 1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与在非阻塞套接字连接中,select() 总是返回 1;但是,我似乎无法找到我的代码出现问题的地方.

This question is very similar (or almost identical) to In a non blocking socket connect, select() always returns 1; however, I can't seem to find where my code is faltering.

我正在使用非阻塞套接字并希望在将客户端连接到服务器时使用 select() 来检查超时/成功.问题是 select() 总是几乎立即返回 1,即使我什至没有运行服务器并且没有任何连接.在此先感谢您的帮助,代码片段如下:

I am using non-blocking sockets and want to use select() when connecting a client to a server to check for timeout/success. The problem is select() is always returning 1 almost immediately, even when I don't even have the server running and there is nothing to connect to. Thanks in advance for the help, code snippet is as follows:

//Loop through the addrinfo structs and try to connect to the first one we can
for(p = serverinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 
    {
        //We couldn't create the socket, try again
        perror("client: socket");
        continue;
    }

    //Set the socket to non-blocking
    int flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
        //The error was something other than non-block/in progress, try next addrinfo
        if(errno != EINPROGRESS) 
        {
            close(sockfd);
            perror("client: connect");
            continue;
        }

        fd_set write_fds;
        FD_ZERO(&write_fds);            //Zero out the file descriptor set
        FD_SET(sockfd, &write_fds);     //Set the current socket file descriptor into the set

        //We are going to use select to wait for the socket to connect
        struct timeval tv;              //Time value struct declaration
        tv.tv_sec = 5;                  //The second portion of the struct
        tv.tv_usec = 0;                 //The microsecond portion of the struct

        //DEBUG: This is ALWAYS 1
        int select_ret = select(sockfd + 1, NULL, &write_fds, NULL, &tv);
        cout << select_ret << endl;

        //Check return, -1 is error, 0 is timeout
        if(select_ret == -1 || select_ret == 0)
        {
            //We had an error connecting
            cout << "Error Connecting
";
            close(sockfd);
            continue;
        }
    }

    //We successfully connected, break out of loop
    break;
}

推荐答案

期望 select() 返回什么?考虑到 select() 通常用于等待多个文件描述符 - 如果您正在连接 两个,您如何仅根据 select 的返回值知道哪个成功/失败?很明显,你不会.

What do you expect select() to return? Consider that select() is normally used to wait for multiple file descriptors - if you were connecting two, how would you know which one succeeded/failed based purely on the return value of select? You wouldn't, obviously.

这就是为什么 select() 只是告诉您哪些文件描述符以某种方式发生了变化,而您应该独立确定那是什么.在connect() 的情况下,您应该调用getsockopt() 来检索连接尝试的结果.请参阅这个答案,其中我解释了如何执行非阻塞连接().

Which is why select() just tells you which file descriptors have changed in some way, and you're supposed to determine independently what that was. In the case of connect(), you should call getsockopt() to retrieve the result of the connection attempt. See this answer where I explain how to do a non-blocking connect().

这篇关于使用 select() 进行非阻塞套接字连接总是返回 1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆