├── 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 | }
--------------------------------------------------------------------------------