-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.c
152 lines (130 loc) · 5.65 KB
/
client.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
/*
I have a struct for the threadLog. This struct stores a thread's:
1. ThreadID: which is assigned in the for loop.
2. socketID: which comes from the server's response.
3. timeOfSpellCheckRequest: Used for saving the time for the spell check
4. timeOfSpellCheckReply: used for saving the time for the response from the server.
5. timeOfThreadTerminationRequest: saving the time the thread got terminated.
*/
typedef struct {
int threadID;
int socketID;
time_t timeOfSpellCheckRequest;
time_t timeOfSpellCheckReply;
time_t timeOfThreadTerminationRequest;
} ThreadLog;
int getRandomNumber();
void printTheClientData(ThreadLog* clientData);
void *clientThreadFunc(void *args);
int getSocketID(char *replyFromSever);
int numberOfClientThreads = 0;
int portNumber = 0;
char *WORDS[] = {"Hello", "this", "how", "awesome", "are", "greatest", "thing", "you", "the", "world", "love"};
int main(int argc, char **argv) {
portNumber = atoi(argv[1]);
numberOfClientThreads = atoi(argv[2]);
// if the numberOfClientThreads are less than 10, give the user an error.
if (numberOfClientThreads < 10) {
perror("The number of client threads must atleast be 10");
exit(EXIT_FAILURE);
}
// creating the number clientThreads, and client_data based on the numberOfClientThreads.
// Waiting for them to join and finish before moving to the next thread.
pthread_t clientThreads[numberOfClientThreads];
ThreadLog client_data[numberOfClientThreads];
for(int i = 0; i < numberOfClientThreads; i++) {
client_data[i].threadID = i;
pthread_create(&clientThreads[i], NULL, clientThreadFunc, &client_data[i]);
pthread_join(clientThreads[i], NULL);
printf("Thread %d finished.\n", i);
printf("\n");
}
return 0;
}
void *clientThreadFunc(void *args) {
// Setting a threadLog pointer to a void ponter argument for that specific thread.
ThreadLog *client_data = (ThreadLog *)(args);
// declaring server of type sockaddr_in
// with specific address family, IP Address and port number
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portNumber);
// Getting a randomNumber and setting a char *randomWord to that
int randomNumber = getRandomNumber();
char *randomWord = WORDS[randomNumber];
// creating a socket here.
int socket_desc = socket(AF_INET, SOCK_STREAM, 0);
// connecting to the server here.
connect(socket_desc, (struct sockaddr *)&server, sizeof(server));
// time of spell check request. This is where I ask for the spell check.
// save the time requesting for spell check and save it in the timeOfSpellCheckRequest for
// the thread's client_data.
struct timespec checkRequest;
clock_gettime(CLOCK_REALTIME, &checkRequest);
client_data->timeOfSpellCheckRequest = checkRequest.tv_sec * 1000 + checkRequest.tv_nsec / 1000000;
// sending the message to the server
char message[256];
strcpy(message, randomWord);
printf("Message before send = %s\n", randomWord);
send(socket_desc, message, strlen(message), 0);
// creating a random delay
int delay = getRandomNumber();
sleep(delay);
char replyFromServer[256];
// receiving the reply from server if there are bytes which I get from the server,
// put a null character at the end.
// The reply from server gets the serverID and then I store the server ID
ssize_t bytesReceivedFromServer = recv(socket_desc, replyFromServer, sizeof(replyFromServer), 0);
if (bytesReceivedFromServer > 0) {
replyFromServer[bytesReceivedFromServer] = '\0';
printf("Received: %s\n", replyFromServer);
} else if (bytesReceivedFromServer == 0) {
printf("Connection closed by the server\n");
} else {
perror("recv");
}
int socketID = getSocketID(replyFromServer);
client_data->socketID = socketID;
// check reply time and storing the reply in the timeOfSpellCheckReply for the thread.
struct timespec checkReply;
clock_gettime(CLOCK_REALTIME, &checkReply);
client_data->timeOfSpellCheckReply = checkReply.tv_sec * 1000 + checkReply.tv_nsec/1000000;
// All the things are done now is the time to terminate the thread, and save that value.
struct timespec threadTerminate;
clock_gettime(CLOCK_REALTIME, &threadTerminate);
client_data->timeOfSpellCheckReply = threadTerminate.tv_sec * 1000 + threadTerminate.tv_nsec/1000000;
// closing the socket_desc
time(&client_data->timeOfThreadTerminationRequest);
printTheClientData(client_data);
close(socket_desc);
return NULL;
}
// Function just returns a random number.
int getRandomNumber() {
int randomNumber = rand() % 10;
return randomNumber;
}
// This prints the perimeters of the clientData
void printTheClientData(ThreadLog* clientData) {
printf("threadId = %d, socketId = %d, timeOfSpellCheckRequest = %ld, timeOfSpellCheckReply = %ld, timeOfThreadTerminationRequest = %ld\n"
,clientData->threadID, clientData->socketID, clientData->timeOfSpellCheckRequest, clientData->timeOfSpellCheckReply, clientData->timeOfThreadTerminationRequest);
}
// This function returns the socketId in the response.
// It passes any char values and stores the integer values, and then I return the integer value.
int getSocketID(char *replyFromServer) {
int number;
if (sscanf(replyFromServer, "%*[^0-9]%d", &number) == 1) {
return number;
} else {
return -1;
}
}