Search code examples
socketstimeoutselect-function

select for timeout over TCP socket


I have a problem with this code:

FD_ZERO(&cset);
FD_SET(s, &cset);

tval.tv_sec = TIMEOUT; 
tval.tv_usec = 0; 

n = select(FD_SETSIZE, &cset, NULL, NULL, &tval);

if (n==-1) {
    printf(" select() failed \n");
    exit(-1);
}
if (n>0) {
    check_control = connect(s,(struct sockaddr*)
    &indirizzo_remoto,sizeof(indirizzo_remoto));

    if (check_control == -1) {
        printf("Errore connect()\n");
    }

}else{
    printf("Timeout. I'll shutdown the client");
    exit(-1);
}

I want insert a timeout for the connect but it doesn't work:

I use the right IP address and port number of the Server but the connection goes to timeout.

Thank you very much for the help.


Solution

  • You are using select() to check if a given socket is in a readable state before calling connect() on that same socket. That will never work. An unconnected TCP socket will never be in a readable state, and cannot be used with select() until connect() has been called on it first.

    The only way to implement a timeout for a connect() call is to put the socket into non-blocking mode first (sockets are blocking by default), then call connect() (which returns an EINPROGRESS error if the socket is attempting to connect), and then use select() to wait for the socket to enter a writable state, indicating the connection was successful, or an error state, indicating the connection failed.

    Try this:

    fcntl(s, F_SETFL, O_NONBLOCK);
    

    Or:

    flags = 1;
    ioctl(s, FIOBIO, &flags);
    

    Depending on your platform.

    Then:

    check_control = connect(s, (struct sockaddr*) &indirizzo_remoto, sizeof(indirizzo_remoto));
    if (check_control == -1)
    {
        if (errno != EINPROGRESS)
        {
            printf("Errore connect()\n");
            exit(-1);
        }
    
        FD_ZERO(&wset);
        FD_SET(s, &wset);
    
        FD_ZERO(&eset);
        FD_SET(s, &eset);
    
        tval.tv_sec = TIMEOUT; 
        tval.tv_usec = 0; 
    
        n = select(s+1, NULL, &wset, &eset, &tval);
        if (n == -1)
        {
            printf(" select() failed \n");
            exit(-1);
        }
    
        if (n == 0)
        {
            printf("Timeout. I'll shutdown the client");
            exit(-1);
        }
    
        if (FD_ISSET(s, &eset))
        {
            printf("Cannot connect. I'll shutdown the client");
            exit(-1);
        }
    
        int err = -1;
        getsockopt(s, SOL_SOCKET, SO_ERROR, &err, sizeof(err));
        if (err != 0)
        {
            printf("Cannot connect. I'll shutdown the client");
            exit(-1);
        }
    }
    
    // connected...