-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.cpp
193 lines (180 loc) · 4.98 KB
/
server.cpp
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <bits/stdc++.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
#include <mutex>
using namespace std;
#define MAX_LEN 256
#define NUM_COLORS 6
string default_colour="\033[0m";
string colors[]={"\033[31m", "\033[32m", "\033[33m", "\033[34m", "\033[35m","\033[36m"};
int client_index_count = 0;
mutex cout_mutex,clients_mutex;
using namespace std;
struct Client{
int client_id;
string client_name;
string client_room;
int client_socket;
thread client_thread;
};
vector<Client> clients;
string color(int code);
void handle_client_connection(int client_socket, int id);
int main(int argc, char *argv[])
{
int PORT = argc > 1 ? atoi(argv[1]) : 0;
if(!PORT)
{
cout<<"Enter Port: \n";
cin>>PORT;
}
int server_socket;
if((server_socket=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("Socket: ");
exit(-1);
}
struct sockaddr_in server;
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr=INADDR_ANY;
bzero(&server.sin_zero,0);
if((bind(server_socket,(struct sockaddr *)&server,sizeof(struct sockaddr_in)))==-1)
{
perror("Bind error: ");
exit(-1);
}
if((listen(server_socket,8))==-1)
{
perror("Listen error: ");
exit(-1);
}
struct sockaddr_in client;
int client_socket;
unsigned int len=sizeof(sockaddr_in);
cout << colors[NUM_COLORS-1]<<"\n\t************CHAT ROOM SERVER: "<<PORT<<"************"<<"\n"<<default_colour;
while(true)
{
if((client_socket = accept(server_socket,(struct sockaddr *)&client,&len)) == -1)
{
perror("Accept error: ");
exit(-1);
}
client_index_count++;
thread connection_thread(handle_client_connection,client_socket,client_index_count);
lock_guard<mutex> guard(clients_mutex);
clients.push_back({client_index_count, string("Anonymous"),"0",client_socket,(move(connection_thread))});
}
for(int i=0; i<clients.size(); i++){
if(clients[i].client_thread.joinable()) clients[i].client_thread.join();
}
close(server_socket);
return 0;
}
string color(int code){return colors[code%NUM_COLORS];}
void set_Client(int id, char name[], char room[])
{
for(int i=0; i<clients.size(); i++)
{
if(clients[i].client_id==id)
{
clients[i].client_name=string(name);
clients[i].client_room=string(room);
}
}
}
void server_print(string str, bool endLine=true)
{
lock_guard<mutex> guard(cout_mutex);
cout<<str;
if(endLine) cout<<endl;
}
int broadcast_to_clients(string message, int sender_id, string sender_room)
{
char temp[MAX_LEN];
strcpy(temp,message.c_str());
for(int i=0; i<clients.size(); i++)
{
if(clients[i].client_id!=sender_id && clients[i].client_room == sender_room)
{
send(clients[i].client_socket,temp,sizeof(temp),0);
}
}
return 1;
}
int broadcast_to_clients(int num, int sender_id, string sender_room)
{
for(int i=0; i<clients.size(); i++)
{
if(clients[i].client_id!=sender_id && clients[i].client_room == sender_room)
send(clients[i].client_socket,&num,sizeof(num),0);
}
return 1;
}
void end_connection(int id, string room)
{
for(int i=0; i<clients.size(); i++)
{
if(clients[i].client_id == id && clients[i].client_room == room)
{
lock_guard<mutex> guard(clients_mutex);
clients[i].client_thread.detach();
clients.erase(clients.begin()+i);
close(clients[i].client_socket);
break;
}
}
}
void handle_client_connection(int client_socket, int id)
{
char name[MAX_LEN],room[MAX_LEN],str[MAX_LEN];
recv(client_socket,name,sizeof(name),0);
recv(client_socket,room,sizeof(room),0);
set_Client(id,name,room);
if(strcmp(name,"__LoadBalancer__") == 0 && strcmp(room,"__getLoad?__") == 0)
{
int noOfClients = clients.size()-1;
send(client_socket,&noOfClients,sizeof(noOfClients),0);
cout<<"Load on this server: "<<noOfClients<<"\n";
}
else
{
string initial_message=string(name)+string(" has joined Room: ");
broadcast_to_clients("#NULL",id, room);
broadcast_to_clients(id,id,room);
broadcast_to_clients(initial_message+room,id,room);
server_print(color(id)+initial_message+room+default_colour);
}
while(true)
{
int bytes_received = recv(client_socket,str,sizeof(str),0);
if(bytes_received <= 0)
return;
if(strcmp(str,"#exit") == 0)
{
if(strcmp(name,"__LoadBalancer__") != 0 || strcmp(room,"__getLoad?__") != 0)
{
string message=string(name)+string(" has left Room: ");
broadcast_to_clients("#NULL",id,room);
broadcast_to_clients(id,id,room);
broadcast_to_clients(message+room,id,room);
server_print(color(id)+message+room+default_colour);
}
else
{
cout<<"Sent Load count to Loadbalancer\n";
}
end_connection(id,room);
return;
}
broadcast_to_clients(string(name),id,room);
broadcast_to_clients(id,id,room);
broadcast_to_clients(string(str),id,room);
}
}