├── README.md ├── client.c └── server.c /README.md: -------------------------------------------------------------------------------- 1 | # Multi-Client-Server-Chat 2 | Group chat program where there is a single server and multiple clients. The server forwards a client's message to all the other clients. 3 | 4 | Platform: Linux with GCC compiler 5 | 6 | Compiling: gcc filename.c -pthread 7 | 8 | Running the server: ./a.out portnumber 9 | 10 | Running the clients: ./a.out username portnumber 11 | 12 | Stopping the clients and server: CTRL-D 13 | 14 | Note: The portnumber provided to clients should be same as the one given to server. Username is just an identity of yourself. 15 | -------------------------------------------------------------------------------- /client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | void *recvmg(void *sock) 11 | { 12 | int their_sock = *((int *)sock); 13 | char msg[500]; 14 | int len; 15 | while((len = recv(their_sock,msg,500,0)) > 0) { 16 | msg[len] = '\0'; 17 | fputs(msg,stdout); 18 | memset(msg,'\0',sizeof(msg)); 19 | } 20 | } 21 | int main(int argc, char *argv[]) 22 | { 23 | struct sockaddr_in their_addr; 24 | int my_sock; 25 | int their_sock; 26 | int their_addr_size; 27 | int portno; 28 | pthread_t sendt,recvt; 29 | char msg[500]; 30 | char username[100]; 31 | char res[600]; 32 | char ip[INET_ADDRSTRLEN]; 33 | int len; 34 | 35 | if(argc > 3) { 36 | printf("too many arguments"); 37 | exit(1); 38 | } 39 | portno = atoi(argv[2]); 40 | strcpy(username,argv[1]); 41 | my_sock = socket(AF_INET,SOCK_STREAM,0); 42 | memset(their_addr.sin_zero,'\0',sizeof(their_addr.sin_zero)); 43 | their_addr.sin_family = AF_INET; 44 | their_addr.sin_port = htons(portno); 45 | their_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 46 | 47 | if(connect(my_sock,(struct sockaddr *)&their_addr,sizeof(their_addr)) < 0) { 48 | perror("connection not esatablished"); 49 | exit(1); 50 | } 51 | inet_ntop(AF_INET, (struct sockaddr *)&their_addr, ip, INET_ADDRSTRLEN); 52 | printf("connected to %s, start chatting\n",ip); 53 | pthread_create(&recvt,NULL,recvmg,&my_sock); 54 | while(fgets(msg,500,stdin) > 0) { 55 | strcpy(res,username); 56 | strcat(res,":"); 57 | strcat(res,msg); 58 | len = write(my_sock,res,strlen(res)); 59 | if(len < 0) { 60 | perror("message not sent"); 61 | exit(1); 62 | } 63 | memset(msg,'\0',sizeof(msg)); 64 | memset(res,'\0',sizeof(res)); 65 | } 66 | pthread_join(recvt,NULL); 67 | close(my_sock); 68 | 69 | } -------------------------------------------------------------------------------- /server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | struct client_info { 11 | int sockno; 12 | char ip[INET_ADDRSTRLEN]; 13 | }; 14 | int clients[100]; 15 | int n = 0; 16 | pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 17 | void sendtoall(char *msg,int curr) 18 | { 19 | int i; 20 | pthread_mutex_lock(&mutex); 21 | for(i = 0; i < n; i++) { 22 | if(clients[i] != curr) { 23 | if(send(clients[i],msg,strlen(msg),0) < 0) { 24 | perror("sending failure"); 25 | continue; 26 | } 27 | } 28 | } 29 | pthread_mutex_unlock(&mutex); 30 | } 31 | void *recvmg(void *sock) 32 | { 33 | struct client_info cl = *((struct client_info *)sock); 34 | char msg[500]; 35 | int len; 36 | int i; 37 | int j; 38 | while((len = recv(cl.sockno,msg,500,0)) > 0) { 39 | msg[len] = '\0'; 40 | sendtoall(msg,cl.sockno); 41 | memset(msg,'\0',sizeof(msg)); 42 | } 43 | pthread_mutex_lock(&mutex); 44 | printf("%s disconnected\n",cl.ip); 45 | for(i = 0; i < n; i++) { 46 | if(clients[i] == cl.sockno) { 47 | j = i; 48 | while(j < n-1) { 49 | clients[j] = clients[j+1]; 50 | j++; 51 | } 52 | } 53 | } 54 | n--; 55 | pthread_mutex_unlock(&mutex); 56 | } 57 | int main(int argc,char *argv[]) 58 | { 59 | struct sockaddr_in my_addr,their_addr; 60 | int my_sock; 61 | int their_sock; 62 | socklen_t their_addr_size; 63 | int portno; 64 | pthread_t sendt,recvt; 65 | char msg[500]; 66 | int len; 67 | struct client_info cl; 68 | char ip[INET_ADDRSTRLEN];; 69 | ; 70 | if(argc > 2) { 71 | printf("too many arguments"); 72 | exit(1); 73 | } 74 | portno = atoi(argv[1]); 75 | my_sock = socket(AF_INET,SOCK_STREAM,0); 76 | memset(my_addr.sin_zero,'\0',sizeof(my_addr.sin_zero)); 77 | my_addr.sin_family = AF_INET; 78 | my_addr.sin_port = htons(portno); 79 | my_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 80 | their_addr_size = sizeof(their_addr); 81 | 82 | if(bind(my_sock,(struct sockaddr *)&my_addr,sizeof(my_addr)) != 0) { 83 | perror("binding unsuccessful"); 84 | exit(1); 85 | } 86 | 87 | if(listen(my_sock,5) != 0) { 88 | perror("listening unsuccessful"); 89 | exit(1); 90 | } 91 | 92 | while(1) { 93 | if((their_sock = accept(my_sock,(struct sockaddr *)&their_addr,&their_addr_size)) < 0) { 94 | perror("accept unsuccessful"); 95 | exit(1); 96 | } 97 | pthread_mutex_lock(&mutex); 98 | inet_ntop(AF_INET, (struct sockaddr *)&their_addr, ip, INET_ADDRSTRLEN); 99 | printf("%s connected\n",ip); 100 | cl.sockno = their_sock; 101 | strcpy(cl.ip,ip); 102 | clients[n] = their_sock; 103 | n++; 104 | pthread_create(&recvt,NULL,recvmg,&cl); 105 | pthread_mutex_unlock(&mutex); 106 | } 107 | return 0; 108 | } --------------------------------------------------------------------------------