Using select() for non-blocking sockets to connect always returns 1

37,248

Solution 1

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

Solution 2

When connecting in non-blocking mode and select() indicates the connection is writeable, you are then supposed to call connect() again. Doing so will return -1 with errno == ECONNRESET or whatever it is.

Share:
37,248
Admin
Author by

Admin

Updated on July 02, 2020

Comments

  • Admin
    Admin almost 4 years

    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;
    }