-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
393 lines (356 loc) · 10.6 KB
/
server.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
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
/* Definations */
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#define MAXBUFLEN 100
#define SOCKET_ERROR -1
#define N_MAX 10000000 //For rand
/* Network */
void *get_in_addr(struct sockaddr *sa);
/* Helper */
char * randStr(int m);
void getInput(char* inp, int size_inp);
void errorExit(char *errorMessage);
void clearScreen();
void AppHeadLine();
void iSleep(float milis);
double getUniRand();
int main(void) {
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv, j;
struct timeval tv1, tv2, tS1, tS2;
double tdiff, lamd;
float xval;
double bigTval;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
char charPort[50]; //store user input for port
char charT[50];
char *charSvrMessage;
char okMsg[] = "OK";
char initMsg[] = "init"; // Broadcast message in this protocol
char readyMsg[] = "ready"; // Server reply ready to serve
char reqMsg[] = "req"; // Client request
int sw = 0; //switch for time record
double activetime; //time to measure serve time
int srvtime;
srand(time(0)); //Seed the pseudo-random number generator
// xval = getUniRand(); //Uncomment this if you want only one xvalue per session
clearScreen();
AppHeadLine();
//Ask port number for server
// return 0;
//Update show x value here
//printf("Server is using x value = %f\n", xval);
//Asking x value if want to modify - no input use rand value
// printf("Please enter xValue\nPress enter (do not put value) to use Rand value\nxVal[%f]:",xval);
// getInput(charPort, sizeof charPort);
// if (strlen(charPort) == 0) {
// printf(
// "- Server will use xVale=%f as default.\n",xval);
// }else{
// xval = atof(charPort);
// }
//init serve time
srvtime=10;
printf("How long do you want to serve client after receiving broadcast packet.\nServe time - Seconds [%d]:",srvtime);
getInput(charPort, sizeof charPort);
if (strlen(charPort) == 0) {
printf(
"- Server will usedefault serve time %d Seconds.\n",srvtime);
}else{
srvtime = atof(charPort);
}
//Clear previous input
memset(&charPort, 0, sizeof(charPort));
printf("Please enter port number to listen\nPort[9999]:");
getInput(charPort, sizeof charPort);
if (strlen(charPort) == 0) {
printf(
"Server can not start without port.\n- Server will use 9999 as default.\n");
strcpy(charPort, "9999"); // use 9999 as default port. Assign it to port since user have no input
//TODO: We will need to check more. E.g: check integer.
}
//
printf(
"Please enter Big T Value \nEnter 0 if you dont want to use drop formula\nmicro sec[10]:");
getInput(charT, sizeof charT);
if (strlen(charT) == 0) {
printf("Server need big T value.\n- Server will use 80 as default.\n");
strcpy(charT, "10"); // use 9999 as default port. Assign it to port since user have no input
//TODO: We will need to check more. E.g: check integer.
}
bigTval = atof(charT);
charSvrMessage = randStr(30);
printf("Server secret message is %s\n", charSvrMessage);
printf("Server is using x value = %f\n", xval);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM; // UDP
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, charPort, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); // Special failure :P
return (EXIT_FAILURE);
}
printf(
"\nNow Server is listening on Port %s \nPlease Broacast your \"init\" message for me.\n",
charPort);
// loop through all the results and bind to the first we can
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol))
== -1) {
errorExit("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
}
if (p == NULL) {
errorExit("listener: failed to bind socket\n");
}
freeaddrinfo(servinfo);
StartWaitClient: printf(
"Server is waiting client \"init\" Broadcast message...\n");
//clear all buffers
addr_len = sizeof their_addr;
//Now waiting for Broadcast
while (1) {
gettimeofday(&tv1, NULL);
sw = 0;
memset(&buf, 0, sizeof(buf));
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0,
(struct sockaddr *) &their_addr, &addr_len)) == -1) {
errorExit("Error: recvfrom");
}
if (strcmp(buf, initMsg) != 0) {
printf("Server: got Broadcast messag from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *) &their_addr), s,
sizeof s));
printf(
"But it is not define in protocol.\nServer is waiting for next Broadcast\nThe message is : %s\n",
buf);
} else {
gettimeofday(&tS1, NULL);
printf("Server: got \"init\" from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *) &their_addr), s,
sizeof s));
printf("Server reply: ready\n");
//Here we are reply
if (sendto(sockfd, readyMsg, sizeof readyMsg, 0,
(struct sockaddr *) &their_addr, addr_len) == -1) {
errorExit("Error: sendto(ready)");
}
break;
}
}
//Now, we reply message length
//Becareful, I try to conver int to char here
int intSvrMsgLen = strlen(charSvrMessage);
char chrMsgLength[100];
sprintf(chrMsgLength , "%d", intSvrMsgLen);
if (sendto(sockfd, chrMsgLength, sizeof chrMsgLength, 0,
(struct sockaddr *) &their_addr, addr_len) == -1) {
errorExit("Error: sendto(message umber)");
}
//Now, try to listen request to send char.
int k = 0;
REARM: printf("Server send char to Client:\n");
for (j = k; j < intSvrMsgLen; j++) {
//Check active interval
gettimeofday(&tS2, NULL);
activetime = (double) (tS2.tv_usec - tS1.tv_usec) / 1000000
+ (double) (tS2.tv_sec - tS1.tv_sec);
//printf("Active %f\n",activetime);
if (activetime > srvtime) {
printf("Serve time is exceed to %d seconds.\n\n\n",srvtime);
goto StartWaitClient;
}
//
memset(&buf, 0, sizeof(buf));
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0,
(struct sockaddr *) &their_addr, &addr_len)) == -1) {
errorExit("Error: recvfrom");
}
//UPDATE : Previous logic is wrong
if (sw == 0) {
gettimeofday(&tv2, NULL);
sw = 1;
} else {
gettimeofday(&tv1, NULL);
sw = 0;
}
//--------------------------------------out is Sec
tdiff = (double) (tv2.tv_usec - tv1.tv_usec) / 1000000
+ (double) (tv2.tv_sec - tv1.tv_sec);
if (tdiff < 0) {
tdiff = tdiff * (-1);
}
tdiff = tdiff * 1000000;
//gettimeofday(&tv1, NULL);
printf(" td: %f ", tdiff);
if (strcmp(buf, reqMsg) != 0) {
errorExit("Error: Invalid Client request");
} else {
char charTemp[1];
charTemp[0] = charSvrMessage[j];
printf("%c", charTemp[0]);
//Here we reply
lamd = tdiff - bigTval;
lamd = lamd * (-1);
lamd = exp(lamd);
if (lamd > 1) {
lamd = 1;
}
printf(" lamd: %f", lamd);
xval = getUniRand();
printf(" x: %f\n", xval);
if (!(lamd > xval) || bigTval == 0) {
if (sendto(sockfd, charTemp, sizeof charTemp, 0,
(struct sockaddr *) &their_addr, addr_len) == -1) {
errorExit("Error: sendto(Char)");
}
}
}
}
printf("Finish string.");
printf("\n");
memset(&buf, 0, sizeof(buf));
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0,
(struct sockaddr *) &their_addr, &addr_len)) == -1) {
errorExit("Error: recvfrom");
}
//printf("%s\n", buf);
if (strcmp(buf, readyMsg) != 0) {
printf("Error: Invalid Client request2\n%d\n%s\n%s",numbytes,buf,readyMsg);
errorExit("Error: Invalid Client request2");
} else {
memset(&buf, 0, sizeof(buf));
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN - 1, 0,
(struct sockaddr *) &their_addr, &addr_len)) == -1) {
errorExit("Error: recvfrom");
}
//Now we compare
for (j = 0; j < intSvrMsgLen; j++) {
if (charSvrMessage[j] == buf[j]) {
} else {
memset(&chrMsgLength, 0, sizeof(chrMsgLength));
sprintf(chrMsgLength, "%d", j);
printf("fault found at : %d\n", j + 1);
//Send it back to client
if (sendto(sockfd, chrMsgLength, sizeof chrMsgLength, 0,
(struct sockaddr *) &their_addr, addr_len) == -1) {
errorExit("Error: sendto()");
}
k = j;
goto REARM;
break;
}
}
if (sendto(sockfd, okMsg, sizeof okMsg, 0,
(struct sockaddr *) &their_addr, addr_len) == -1) {
errorExit("Error: sendto()");
}
printf("\nClient successfully provide correct string.\nNow Server will exit.\n\n");
}
close(sockfd);
return 0;
}
/* Network Functions */
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*) sa)->sin_addr);
}
return &(((struct sockaddr_in6*) sa)->sin6_addr);
}
int isReadable(int sd, int * error, int timeOut) { // milliseconds
fd_set socketReadSet;
FD_ZERO(&socketReadSet);
FD_SET(sd, &socketReadSet);
struct timeval tv;
if (timeOut) {
tv.tv_sec = timeOut / 1000;
tv.tv_usec = (timeOut % 1000) * 1000;
} else {
tv.tv_sec = 0;
tv.tv_usec = 0;
} // if
if (select(sd + 1, &socketReadSet, 0, 0, &tv) == SOCKET_ERROR) {
*error = 1;
return 0;
} // if
*error = 0;
return FD_ISSET(sd, &socketReadSet) != 0;
} /* isReadable */
/* Helper functions */
char * randStr(int m) {
int i, s = m; //int i,s=1 + rand()%m;
char t;
char * word = (char *) malloc(s);
for (i = 0; i < s; ++i) {
t = rand() % 52;
word[i] = 'A' + (t >> 1) + ((1 & t) << 5);
}
word[i] = '\0';
return word;
}
void iSleep(float milis) {
usleep(milis * 100);
}
void getInput(char* inp, int size_inp) {
fflush (stdout);
fgets(inp, size_inp, stdin);
char *enterchar = strchr(inp, '\n'); /* search for newline character */
if (enterchar != NULL) {
*enterchar = '\0'; /* overwrite trailing newline */
}
}
void errorExit(char *errorMessage) {
perror(errorMessage);
exit(EXIT_FAILURE); /* Exit App with error. If another app is calling this App, they know this status*/
}
void clearScreen() {
const char* CLEAR_SCREE_ANSI = "\e[1;1H\e[2J";
write(STDOUT_FILENO, CLEAR_SCREE_ANSI, 12);
}
void AppHeadLine() {
printf(
"__________________________________________________________________________\n\n");
printf("Game Server Application\n");
printf(
"__________________________________________________________________________\n\n");
}
double getUniRand() {
double x;
x = (double) rand() / (double) RAND_MAX;
return x;
// int i;
// double sum_0, sum_1, mean, var, x;
// for (i = 1, sum_0 = 0., sum_1 = 0.; i <= N_MAX; i++) {
// sum_0 += x;
// sum_1 += (x - 0.5) * (x - 0.5);
// }
// mean = sum_0 / (double) N_MAX;
// var = sum_1 / (double) N_MAX;
}