#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    1
    Rep Power
    0

    Multiple client connections


    Hi,

    I have a simple tcp server, to which i would like to add support for multiple client connections via pthreads. This is what i had in mind, calling accept in a separate thread.

    I this similar to what you would do?
    Code:
       .
       .
    int sock = socket(PF_INET,SOCK_STREAM,0);
    int sock_fd[10];
    struct sockaddr_in client_addr[10];
    int size = sizeof(&client_addr);
    
    void *Thread1(void *arg){
    
    
       for(i=0;i<9;i++){
      sock_fd[i] = accept(sock,(struct sockaddr *)&client_addr[i],size);
    
    }
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,183
    Rep Power
    2222
    OK, that's a start. How are you handling the client sockets?

    Also, that array of client socket file descriptors is being changed by your accept thread by adding new clients, but somewhere else in your program it's also being changed by removing clients who have disconnected. That makes that array a critical region that needs to by synchronized. Also, keeping the client count as a local variable doesn't do that other portion of your code any good, nor any portion that has to make use of that array and hence know how many clients there are. If you make the client count a global as well, it will need to be part of the same critical region as the fd array.

    Hopefully, none of what I just told you is new to you. If it is, then you might want to read up some more on the subject. A few years ago on my site I explored the topic of handling multiple sockets under the subject of dealing with blocking sockets. Here is a link to the multiprocessing/multithreading portion of that page: http://pgm.dwise1.net/sockets/blocking.html#THREADS. I haven't worked with it extensively, but maybe some of the ideas and the discussion might help.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    187
    Rep Power
    82
    Originally Posted by brown_mist
    Hi,

    I have a simple tcp server, to which i would like to add support for multiple client connections via pthreads. This is what i had in mind, calling accept in a separate thread.

    I this similar to what you would do?
    Code:
       .
       .
    int sock = socket(PF_INET,SOCK_STREAM,0);
    int sock_fd[10];
    struct sockaddr_in client_addr[10];
    int size = sizeof(&client_addr);
    
    void *Thread1(void *arg){
    
    
       for(i=0;i<9;i++){
      sock_fd[i] = accept(sock,(struct sockaddr *)&client_addr[i],size);
    
    }
    I just can't make the connection (no pun intended) between the code snippet you posted and implementing pthreads for a server. So, listed below is a bare bones server implementation using pthreads with some documentation.

    Code:
    // Compile gcc server.c -o server -lpthread
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <sys/uio.h>
    #include <unistd.h>
    #include <pthread.h>
    
    // Port that we will be using
    #define TCP_PORT   6600
    
    /* function prototypes and global variables */
    void *child_thread(void * arg);
    pthread_mutex_t lock;
    // This is just a cumulative count of how many clients have connected
    // since the server was started
    int	cumtotalconnections;
    
    int main(void)
    {
        int sockfd, newsockfd, clientlength;
        struct sockaddr_in cli_addr, serv_addr;
        pthread_t chld_thread;
    
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            fprintf(stderr,"server can't open socket\n"), exit(0);
    
        memset((char *) &serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_addr.sin_port = htons(TCP_PORT);
    
        if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
            fprintf(stderr,"server can't bind local address\n"), exit(0);
        // The OS threading library maintains a pool of Light Weight Processes, LWPs that it uses to run
        // all the process-scoped user threads.
        // It can reschedule these user threads onto LWPs in the pool as the need arises.
        // The size of this pool can be adjusted via the Pthreads pthread_setconcurrency() function.
        pthread_setconcurrency(5);
        listen(sockfd, 5);
        for(;;) {
            clientlength = sizeof(cli_addr);
            newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clientlength);
    
            if(newsockfd < 0)
                fprintf(stderr,"server has an accept error\n"), exit(0);
    
            /* create a new thread to process the incomming request */
            pthread_create(&chld_thread, NULL, child_thread, (void *)newsockfd);
            // the server is now free to accept another socket request
            // since pthread_create is a asynchronous function
        }
        return(0);
    }
    
    // Function executed from a new thread
    
    void *child_thread(void *arg)
    {
        int 	socketfd = (int) arg;
        char 	data[124]= {0};
    
        printf("Child thread [%d]: Socket number = %d\n", (int)pthread_self(), socketfd);
        /* read from the given socket */
        read(socketfd, data, 48);
        printf("Child thread [%d]: My data = %s\n", (int)pthread_self(), data);
    	// POSIX threads defines a new data type called a mutex, which stands for mutual exclusion.
    	// A mutex is used to insure either that only one thread is executing a particular piece of code at
    	// once (code locking) or that only one thread is accessing a particular data structure at once (data locking).
    	// A mutex belongs either to a particular thread or to no thread (i.e., it is either locked or unlocked).
    	// A thread may lock a mutex by calling pthread_mutex_lock. If no other thread has the mutex locked,
    	// then the calling thread obtains the lock on the mutex and returns. Otherwise it waits until no other thread has the mutex,
    	// and finally returns with the mutex locked. There may, of course, be multiple threads waiting for the mutex to be unlocked.
    	// Only one thread can lock the mutex at a time; there is no specified order for which thread gets the mutex next,
    	// though the ordering is assumed to be at least somewhat fair.
    	// To unlock a mutex, a thread calls pthread_mutex_unlock.
    
    	// use a mutex to update the global cumtotalconnections
    
        pthread_mutex_lock(&lock);
        cumtotalconnections++;
        pthread_mutex_unlock(&lock);
        /* close the socket and exit this thread */
        close(socketfd);
        pthread_exit((void *)0);
    }

IMN logo majestic logo threadwatch logo seochat tools logo