Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
825 views
in Technique[技术] by (71.8m points)

c - Using select() for non-blocking sockets to connect always returns 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.

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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...