multithread server/client implementation in C

88,005

Solution 1

You can create multiple clients using thread. Create a separate thread for each client and then from thread handler connect to the server. I am not sure if it is a good way or not.

Code:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_SIZE 50
#define NUM_CLIENT 5
void *connection_handler(void *socket_desc);
int main()
{
    int socket_desc , new_socket , c , *new_sock, i;
    pthread_t sniffer_thread;
    for (i=1; i<=NUM_CLIENT; i++) {
        if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) i) < 0)
        {
            perror("could not create thread");
            return 1;
        }
        sleep(3);
    }
    pthread_exit(NULL);
    return 0;
}

void *connection_handler(void *threadid)
{
    int threadnum = (int)threadid;
    int sock_desc;
    struct sockaddr_in serv_addr;
    char sbuff[MAX_SIZE],rbuff[MAX_SIZE];

    if((sock_desc = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        printf("Failed creating socket\n");

    bzero((char *) &serv_addr, sizeof (serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(8888);

    if (connect(sock_desc, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
        printf("Failed to connect to server\n");
    }

    printf("Connected successfully client:%d\n", threadnum);
    while(1)
    {
        printf("For thread : %d\n", threadnum);
        fgets(sbuff, MAX_SIZE , stdin);
        send(sock_desc,sbuff,strlen(sbuff),0);

        if(recv(sock_desc,rbuff,MAX_SIZE,0)==0)
            printf("Error");
        else
           fputs(rbuff,stdout);

        bzero(rbuff,MAX_SIZE);
        sleep(2);
    }
    close(sock_desc);
    return 0;
}

For understanding purpose, i used sleep.

REF:

http://www.amazon.com/UNIX-Network-Programming-Richard-Stevens/dp/0139498761

http://beej.us/guide/bgnet/

https://computing.llnl.gov/tutorials/pthreads/

Solution 2

Firstly, if you fork(), you will be creating additional processes, not additional threads. To create additional threads, you want to use pthread_create.

Secondly, as you are a student, the canonical answer here is 'read Stephens'. Not only is this an invaluable tool even for those of us experienced in writing socket I/O routines, but also it contains examples of non-threaded non-forking async I/O, and various ways to add threads and forking to them. I believe the one you want is: http://www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321637739 (chapter 14 if memory serves). This should be in your college library.

Share:
88,005
Shikhar Deep
Author by

Shikhar Deep

Android Developer

Updated on July 09, 2022

Comments

  • Shikhar Deep
    Shikhar Deep almost 2 years

    I have just started learning basic networking concepts.I am trying to implement a multithread server-client prog in C.but the problem is instead of running multiple windows/terminals/instances for clients,i should use fork() to create children of client.so by creating children of client multiple clients will be created.now each of these child clients will communicate with the server on a thread.

    Earlier i created a similar prog but in that for multiple client you have to open multiple windows for clients and run all of them.

    I am having trouble where to modify my code (both in server and client ones.I think server one is ok.but i am having no idea where to fork() in client program and what changes should be made).

    Actually i don't want to open multiple windows to run multiple client,thats why i am using fork() to create multiple copies of it.Is there any other way by which i can create multiple clients and connect them to my server prog via threads.

    Server :

    // socket server example, handles multiple clients using threads
    
    #include<stdio.h>
    #include<string.h>    //strlen
    #include<stdlib.h>    //strlen
    #include<sys/socket.h>
    #include<arpa/inet.h> //inet_addr
    #include<unistd.h>    //write
    #include<pthread.h> //for threading , link with lpthread
    
    //the thread function
    void *connection_handler(void *);
    
    int main(int argc , char *argv[])
    {
        int socket_desc , client_sock , c , *new_sock;
        struct sockaddr_in server , client;
    
        //Create socket
        socket_desc = socket(AF_INET , SOCK_STREAM , 0);
        if (socket_desc == -1)
        {
            printf("Could not create socket");
        }
        puts("Socket created");
    
        //Prepare the sockaddr_in structure
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons( 3000 );
    
        //Bind
        if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
        {
            //print the error message
            perror("bind failed. Error");
            return 1;
        }
        puts("bind done");
    
        //Listen
        listen(socket_desc , 3);
    
        //Accept and incoming connection
        puts("Waiting for incoming connections...");
        c = sizeof(struct sockaddr_in);
    
            c=sizeof(struct sockaddr_in);
           while(client_sock=accept(socket_desc,(struct sockaddr*)&client,(socklen_t*)&c))
           {
            puts("Connection accepted");
    
            pthread_t sniffer_thread;
            new_sock = malloc(1);
            *new_sock = client_sock;
    
            if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0)
            {
                perror("could not create thread");
                return 1;
            }
    
            puts("Handler assigned");
        }
    
        if (client_sock < 0)
        {
            perror("accept failed");
            return 1;
        }
        return 0;
    }
    /*
      This will handle connection for each client
      */
    void *connection_handler(void *socket_desc)
    {
        //Get the socket descriptor
        int sock = *(int*)socket_desc;
        int n;
    
            char    sendBuff[100], client_message[2000];
    
          while((n=recv(sock,client_message,2000,0))>0)
          {
    
            send(sock,client_message,n,0);
          }
          close(sock);
    
          if(n==0)
          {
            puts("Client Disconnected");
          }
          else
          {
            perror("recv failed");
          }
        return 0;
    }
    

    Client:

    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define MAX_SIZE 50
    
    int main()
    {
        int sock_desc;
        struct sockaddr_in serv_addr;
        char sbuff[MAX_SIZE],rbuff[MAX_SIZE];
    
        if((sock_desc = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            printf("Failed creating socket\n");
    
        bzero((char *) &serv_addr, sizeof (serv_addr));
    
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        serv_addr.sin_port = htons(3000);
    
        if (connect(sock_desc, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
            printf("Failed to connect to server\n");
            return -1;
        }
    
        printf("Connected successfully - Please enter string\n");
        while(fgets(sbuff, MAX_SIZE , stdin)!=NULL)
        {
          send(sock_desc,sbuff,strlen(sbuff),0);
    
              if(recv(sock_desc,rbuff,MAX_SIZE,0)==0)
               printf("Error");
              else
               fputs(rbuff,stdout);
    
           bzero(rbuff,MAX_SIZE);//to clean buffer-->IMP otherwise previous word characters also came
        }
            close(sock_desc);
        return 0;
    
    }