Search code examples
csocketsclientlisten

Client Calling connect() without server calling listen()


I have a normal server and client TCP C program that uses sockets. It works perfectly when server is started first (i.e. server calls listen() and then waits for client to call connect()).

Now, what I want to implement is a situation where the client is started first, and the server is started at any later time.

The client should keep trying to connect to the server. Until server is OFF, I know that the client's connect() call will return -1; but the client should keep trying until a successful connection is established.

Currently on the client side, I am trying to call connect() in a while loop but it will not work if server isn't already listening when the client runs.

Client connect code:

while( 1)
    {
        
        for(int j=0; j<argc-3; j++){
            //sockfd of each server needed to be connect()ed is stored in array all_sock_fd[]

            if ((sender_conn=connect(all_sock_fd[j], (struct sockaddr *)&all_sockaddrs[j],sizeof(struct sockaddr)) == -1)) {
                
                //do nothing if fails
            }
            else{ //if connection successful then create a thread for that connection
                if( pthread_create( &thread_id , NULL ,  you_connect_to_others , (void*) &all_sock_fd[j]) < 0)
                {
                    perror("could not create thread");
                    return 1;
                }
                
            }
        }
}

The code above works fine when Servers are listen()-ing already before client calls connect(). But if the client is run before the server (i.e. if server starts 2 seconds after client) then this code will never connect.

I tried the while loop approach where the client keeps trying to call connect() hoping that when server finally calls listen(), a connection will be established.

But this does not work. Even when server is turned ON after the client, The connection never happens.

Can I use select() or poll() for this? If so , how?


Solution

  • Your code is mostly correct. However, you need to close and recreate the socket on each loop iteration (see Does socket become unusable after connect() fails?), eg:

    for(int j = 0; j < argc-3; j++){
        //sockfd of each server needed to be connect()ed is stored in array all_sock_fd[]
        int sockfd;
        while (1)
        {
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0)
            {
                perror("could not create socket");
                return 1; 
            }
    
            sender_conn = connect(sockfd, (struct sockaddr *)&all_sockaddrs[j], sizeof(all_sockaddrs[j]));
            if (sender_conn == 0) break;
    
            // examine errno and decide whether it is reasonable to continue retrying
    
            close(sockfd);
    
            //wait a few seconds and try again
            sleep(5);
        }
    
        //connection successful, create a thread for that connection
        all_sock_fd[j] = sockfd;
        if (pthread_create(&thread_id, NULL, you_connect_to_others, (void*) &all_sock_fd[j]) < 0)
        {
           perror("could not create thread");
           close(all_sock_fd[j]);
           all_sock_fd[j] = -1;
           return 1; 
        }
    }