-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmulticlientchatserver.c
141 lines (119 loc) · 3.89 KB
/
multiclientchatserver.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
Select()
A better way to handle multiple clients is by using select() linux command.
Select command allows to monitor multiple file descriptors, waiting until one of the file descriptors become active.
For example, if there is some data to be read on one of the sockets select will provide that information.
Select works like an interrupt handler, which gets activated as soon as any file descriptor sends any data.
Data structure used for select: fd_set
It contains the list of file descriptors to monitor for some activity.
There are four functions associated with fd_set:
fd_set readfds;
// Clear an fd_set
FD_ZERO(&readfds);
// Add a descriptor to an fd_set
FD_SET(master_sock, &readfds);
// Remove a descriptor from an fd_set
FD_CLR(master_sock, &readfds);
//If something happened on the master socket , then its an incoming connection
FD_ISSET(master_sock, &readfds);
manual page of select : https://linux.die.net/man/2/select
activity = select( max_fd + 1 , &readfds , NULL , NULL , NULL);
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>//for FD macros
#define PORT 4444
int main(){
int sockfd, ret,maxsd=0,sd;//temporary variables to store socket descriptor
struct sockaddr_in serverAddr;
int i, socketcount, bytesize;
int newSocket;
int clientsocket[10];//Hold all the socket numbers of client
struct sockaddr_in newAddr;
fd_set readfds;//File descriptor set to handle all fds.
FD_ZERO(&readfds);//Clear the file descriptor set
socklen_t addr_size;
char buffer[1024];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Server Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
for (i = 0; i < 10; i++)//Initialise the client sockets to 0
{
clientsocket[i] = 0;
}
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in binding.\n");
exit(1);
}
printf("[+]Bind to port %d\n", 4444);
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
printf("[-]Error in listening.\n");
}
while(1){
bzero(buffer, sizeof(buffer));
FD_ZERO(&readfds);//Clear the fd_set
FD_SET( sockfd, &readfds);//Insert the master socket into the fd-set
maxsd = sockfd;
for(i=0;i<10;i++){
sd = clientsocket[i];
if(sd>0)
FD_SET(clientsocket[i],&readfds);//Insert the client to fd-set if a valid socket and not 0
if(sd>maxsd){//get the highest descriptor number for first argument of select function
maxsd = sd;
}
}
socketcount = select( maxsd+1, &readfds, NULL, NULL, NULL );
if(socketcount<1){
printf("[-]Error in select");
}
if(FD_ISSET(sockfd, &readfds)){//Check if the activity is on master socket for incoming connection
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0){
printf("[-]Error in accepting.\n");
exit(1);
}
printf("[+]Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
strcpy(buffer,"Hey, Welcome to the Chat Server");
send(newSocket, buffer, strlen(buffer), 0);
for(i=0;i<10;i++){
if(clientsocket[i]==0)
clientsocket[i]=newSocket;
break;
}
}
else{
for(i=0;i<10;i++){
sd = clientsocket[i];
if(FD_ISSET(sd, &readfds)){
bytesize = recv(sd, buffer, 1024,0);
if(bytesize==0){
close(sd);
clientsocket[i]=0;
}
else{
buffer[bytesize]='\0';
send(sd,buffer,strlen(buffer),0);
}
}
}
}
}
close(sockfd);
return 0;
}