Multiple Client Server connections in C

I am trying to explain how a simple server implemented in C with sockets can handle concurrent clients. Let's say a simple server waits for the client to connect and then reads the message sent from the client. The read () function is a blocking function, so the server will block until the client writes to it. If we assume two clients are logging into the server at the same time. The server will wake up to one of them, but what will happen to the other? is the server still "listening" on the request from the first client? I know that the bind function takes an int as the second argument which indicates the lag (default 5). does this mean only 5 clients can connect to the server at the same time? If that's true, how are servers implemented that handle multiple concurrent connections?

+3


source to share


4 answers


You need streams. Servers usually have a main thread that listens for a connection. If the connection is complete, the main thread created another thread and passes that connection to the newly created thread. In this way, connections are responsive while the main thread is still able to listen for new connections.

Edit: Here is the audition ():

listen(int socket_fd, int backlog)



The kernel maintains two queues for a given listening socket.

  • An incomplete connection queue for which a SYN was received, but the three-way handshake (TCP) is incomplete. (SYN_RCV state) Full connection queue
  • A three-way handshake performed. (ESTABLISHED state) The backlog argument historically defines the sum of both queues. But there is no formal definition of what lagging means.
+2


source


select(2)

and poll(2)

a bell system was invented to address this particular situation (s ). non-blocking sockets

Then there is the multiprocessing approach with fork(2)

, and then of course the server can be implemented with threads .



The best solution for your case depends on your specific requirements.

+4


source


I believe one way is to accept joins in a loop. Then process each accepted connection on a separate thread. An example of how to do it here *. The basic approach is shown here:

 while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
 {
        puts("Connection accepted");

        pthread_t sniffer_thread;

        // Copy the value of the accepted socket, in order to pass to the thread
        new_sock = malloc(4);
        *new_sock = client_sock;

        // Create new thread  
        if( pthread_create( &sniffer_thread, NULL,  connection_handler, new_sock) < 0)
        {
            perror("could not create thread");
            return 1;
        }

        //Now join the thread , so that we dont terminate before the thread
        //pthread_join( sniffer_thread , NULL);
        puts("Handler assigned");
    }

      

*: The code in this example may not be perfect, but at least you should get the idea. For example, I don't understand why the author was allocating one byte for an int. Also see.

+2


source


using this function on the server:

int listen(int sockfd, int backlog); 

      

The "backlog" indicates how many distinguished clients can try to connect at one time.

When this function returns:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);  

      

then immediately by passing the 'sockfd' parameter to

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                      void *(*start_routine) (void *), void *arg);  

      

for the thread to handle communication with the client.

Note: creating a thread is expensive and slow, so you first need to create a "pool" of threads and activate it for each client connection, and when the client disconnects, return the thread to the pool

+1


source







All Articles