-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMultiplexingServer.cpp
194 lines (153 loc) · 5.4 KB
/
MultiplexingServer.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
194
#include "MultiplexingServer.h"
MultiplexingServer::MultiplexingServer():
socketCreator()
{
try
{
socketCreator.createSocket(&requestSocket, AF_INET); // set up the listening socket by giving the socket and protocol
FD_ZERO(&actionFlag); // set status flag to zero
FD_SET(requestSocket, &actionFlag); // set up status flag for listen socket
for(int i = 0;i < MAXCLIENTS;i++) // set all client sockets to invalid
clients[i] = INVALID_SOCKET;
}
catch(string failure) // if something fails print error
{
printf("%s", failure.c_str());
}
}
MultiplexingServer::~MultiplexingServer()
{
closeSockets(); // close all socktes and cleanup
WSACleanup();
}
void MultiplexingServer::configServer(const unsigned short port)
{
int errorCode;
memset(&localhost, 0, sizeof(SOCKADDR_IN)); // reset the localhost address to zero
localhost.sin_family = AF_INET; // set the protocol, tcp/ip in this case
localhost.sin_port = htons(port); // set the port
localhost.sin_addr.s_addr = ADDR_ANY; // set standard ip address
printf("\nBinding socket...");
errorCode = bind(requestSocket, (SOCKADDR*)&localhost, sizeof(SOCKADDR_IN)); // bind the listen socket and get error code
if(errorCode == SOCKET_ERROR)
{
closeRequestSocket(); // if something goes wrong, close socket
throw exceptionTexter("\nFAIL: Unable to bind socket! (Error Code: ", errorCode); // throw message with error code
}
else
printf("\nSUCCESS: Bound socket to port %u!", port);
printf("\nStarting listen mode...");
errorCode = listen(requestSocket, 10); // start listening and get error code
if(errorCode == SOCKET_ERROR) // our standard error handling
{
closeRequestSocket();
throw exceptionTexter("\nFAIL: Unable to initiate listen mode! (Error Code: ", errorCode);
}
else
{
printf("\nSUCCESS: Listen mode started!");
}
}
void MultiplexingServer::clientListener(void)
{
int errorCode;
char* command[2]; // command string for login, logout, follow
setClientToOnline(); // set client stati to online
errorCode = select(1000, &actionFlag, NULL, NULL, 0); // select client
if(errorCode == SOCKET_ERROR) // check for error
throw exceptionTexter("\nFAIL: Something went wrong with SELECT! (Error Code: ", errorCode);
if(FD_ISSET(requestSocket, &actionFlag)) //
{
try
{
acceptClient(); // call our accept client function
}
catch(string failure) // check for errors
{
printf("%s", failure.c_str());
}
}
for(int i = 0;i < MAXCLIENTS;i++) // iterate through all client sockets
{
if(clients[i] != INVALID_SOCKET && FD_ISSET(clients[i], &actionFlag)) // if current client is valid and set online
{
try
{
//FIXME: escaping character for command
receive(&clients[i]); // call our receive messages function
commandInterpreter(command, clients[i]); // call our interpret commands function
delete [] command[1];
delete [] command[0];
}
catch(const char* failure) // on failure set client offline and print error
{
printf("%s", failure);
setClientToOffline(&clients[i]);
}
}
}
}
void MultiplexingServer::acceptClient(void)
{
for(int j = 0;j < MAXCLIENTS;j++) // go through all possible sockets
{
if(clients[j] == INVALID_SOCKET) // if the current socket is invalid
{
clients[j] = accept(requestSocket, NULL, NULL); // you can accept the client here
if(clients[j] == INVALID_SOCKET)
throw exceptionTexter("\nFAIL: Couldn't connect client! (socket ", clients[j]);
else
{
printf("\nSUCCESS: Connected with client! (socket %d)", clients[j]);
break;
}
}
}
}
void MultiplexingServer::sendToClient(const SOCKET* client, const char* message)
{
//TODO: check if whole message was sent
int errorCode;
// send a message to a client/tweeter by giving the client socket, message and size
errorCode = send(*client, message, BUFFERSIZE, 0);
if(errorCode == SOCKET_ERROR)
throw exceptionTexter("\nFAIL: Unable to send message! (Error Code: ", errorCode);
}
void MultiplexingServer::receive(const SOCKET* clientSocket)
{
//TODO: check if we received the whole message
int errorCode;
// receive a message by the client socket, content and size
errorCode = recv(*clientSocket, clientMessage, BUFFERSIZE, 0);
if(errorCode == 0)
throw exceptionTexter("\nFAIL: Lost connection to client! (Error Code: ", errorCode);
else if(errorCode == SOCKET_ERROR)// || !strcmp("offline", clientMessage))
throw exceptionTexter("\nClient went offline! (socket ", *clientSocket);
}
void MultiplexingServer::setClientToOffline(SOCKET* clientSocket)
{
closesocket(*clientSocket); // close the given client socket
*clientSocket = INVALID_SOCKET; // and set it to invalid
FD_ZERO(&actionFlag); // set the status flag to zero
FD_SET(requestSocket, &actionFlag); // set the status flag for the request socket to zero to be available again
}
void MultiplexingServer::setClientToOnline(void)
{
for(int i = 0; i < MAXCLIENTS;i++) // go through all possible sockets
{
if(clients[i] != INVALID_SOCKET) // if it is not invalid
FD_SET(clients[i], &actionFlag); // set the status to active
}
}
void MultiplexingServer::closeRequestSocket(void) const
{
closesocket(requestSocket); // close the listen socket and cleanup
WSACleanup();
}
void MultiplexingServer::closeSockets(void)
{
closesocket(requestSocket);
FD_ZERO(&actionFlag);
for(int i = 0;i < MAXCLIENTS;i++) // close all possible sockets
closesocket(clients[i]);
}