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

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

问题描述

这个问题是非常相似的(或几乎相同)<一个href=\"http://stackoverflow.com/questions/5843810/in-a-non-blocking-socket-connect-select-always-returns-1\">In非阻塞套接字连接,请选择()始终返回1 ;不过,我似乎无法找到在我的code是步履蹒跚。

我使用非阻塞套接字,并要使用选择客户端连接到服务器,检查超时/成功时,()。问题是选择()总是返回1几乎立刻,甚至当我甚至不具备服务器上运行并没有什么连接到。在此先感谢您的帮助,code片断如下:

  //循环遍历addrinfo中的结构,并尝试连接到我们可以第一个
为(P = serverinfo; P!= NULL; P = P-&GT; ai_next){
    如果((的sockfd =插座(对GT; ai_family,P-&GT; ai_socktype,P-&GT; ai_protocol))== -1)
    {
        //我们无法创建插座,再试一次
        PERROR(客户端:套接字);
        继续;
    }    //设置套接字非阻塞
    诠释标志=的fcntl(的sockfd,F_GETFL,0);
    的fcntl(的sockfd,F_SETFL,旗帜| O_NONBLOCK);    如果(连接(的sockfd,P-&GT; ai_addr,P-&GT; ai_addrlen)== -1){
        //错误是比非块以外的东西/正在进行中,尝试下addrinfo中
        如果(错误!= EINPROGRESS)
        {
            接近(的sockfd);
            PERROR(客户端:连接);
            继续;
        }        FD_SET write_fds;
        FD_ZERO(安培; write_fds); //零了文件描述符集
        FD_SET(的sockfd,&安培; write_fds); //设置当前套接字文件描述符入套        //我们将使用select来等待套接字连接
        timeval结构电视; //时间值结构声明
        tv.tv_sec = 5; //该结构的第二部分
        tv.tv_usec = 0; //该结构的微秒部分        // DEBUG:这始终是1
        INT select_ret =选择(的sockfd + 1,NULL,&安培; write_fds,NULL,&安培;电视);
        COUT&LT;&LT; select_ret&LT;&LT; ENDL;        //检查回报,-1错误,0是超时
        如果(select_ret == -1 || select_ret == 0)
        {
            //我们有连接错误
            COUT&LT;&LT; 错误连接\\ N的;
            接近(的sockfd);
            继续;
        }
    }    //我们连接成功,打破循环
    打破;
}


解决方案

你是什么期望的选择()返回?认为选择()通常用于等待多个文件描述符 - 如果你连接的两个的,你怎么知道哪一个成功/失败纯粹的选择返回值基础?你也不会,很明显。

这也是为什么选择()只是告诉你哪些文件描述符以某种方式变了,你应该确定独立那是什么东西。在Connect()的情况下,你应该调用的getsockopt()来获取连接尝试的结果。见<一href=\"http://stackoverflow.com/questions/10187347/async-connect-and-disconnect-with-epoll-linux/10194883#10194883\">this回答在这里我解释一下如何做一个非阻塞连接()。

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.

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\n";
            close(sockfd);
            continue;
        }
    }

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

解决方案

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.

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天全站免登陆