-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient.cpp
More file actions
172 lines (135 loc) · 4.46 KB
/
client.cpp
File metadata and controls
172 lines (135 loc) · 4.46 KB
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
#include <sys/types.h> // size_t, ssize_t
#include <sys/socket.h> // socket funcs
#include <netinet/in.h> // sockaddr_in
#include <arpa/inet.h> // htons, inet_pton
#include <unistd.h> // close
#include <iostream>
#include <fstream>
#include <string>
#include <pthread.h>
#include <semaphore.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int UNISIGNED_SHORT_LENGTH = 5;
template <typename T_STR, typename T_CHAR>
T_STR remove_leading(T_STR const & str, T_CHAR c)
{
auto end = str.end();
for (auto i = str.begin(); i != end; ++i) {
if (*i != c) {
return T_STR(i, end);
}
}
// All characters were leading or the string is empty.
return T_STR();
}
void send(string msgStr, int sock, int size) {
string newString = string(size - msgStr.length(), '0') + msgStr;
size++;
char msg[size];
strcpy(msg, newString.c_str());
msg[size - 1] = '\n'; // Always end message with terminal char
int bytesSent = send(sock, (void *) msg, size, 0);
if (bytesSent != size) {
cerr << "TRANSMISSION ERROR" << endl;
exit(-1);
}
}
string read(int messageSizeBytes, int socket) {
int bytesLeft = messageSizeBytes; // bytes to read
char buffer[messageSizeBytes]; // initially empty
char *bp = buffer; //initially point at the first element
while (bytesLeft > 0) {
int bytesRecv = recv(socket, (void *)bp, bytesLeft, 0);
if (bytesRecv <= 0) {
cerr << "Error receiving message" << endl;
exit(-1);
}
bytesLeft = bytesLeft - bytesRecv;
bp = bp + bytesRecv;
}
return string(buffer);
}
int getSocket(char *IPAddr, unsigned short servPort) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
cerr << "Error with socket" << endl; exit (-1);
}
// Convert dotted decimal address to int
unsigned long servIP;
int status = inet_pton(AF_INET, IPAddr, (void*)&servIP);
if (status <= 0) exit(-1);
// Set the fields
struct sockaddr_in servAddr;
servAddr.sin_family = AF_INET; // always AF_INET
servAddr.sin_addr.s_addr = servIP;
servAddr.sin_port = htons(servPort);
status = connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr));
if (status < 0) {
cerr << "Error with connect" << endl;
exit (-1);
}
return sock;
}
int getInput() {
int i;
if ( cin>>i )
return i;
else
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 100000; // Something intentionally out of range.
}
int main(int argc, char** argv) {
if (argc < 3) {
cerr << "CLIENT MUST BE STARTED WITH IP and PORT" << endl;
cerr << "Example: ./client 0.0.0.0 11700" << endl;
exit(-1);
}
char *IPAddr = argv[1]; // IP Address
const unsigned short servPort = (unsigned short) strtoul(argv[2], NULL, 0);
string playerName;
cout << "Welcome to Number Guessing Game! Enter your name: ";
cin >> playerName;
playerName += string(" "); // Breathing room: makes printing prettier
int socket = getSocket(IPAddr, servPort);
unsigned short nameLength = htons(short(playerName.length()));
send(to_string(nameLength), socket, 5); // Send name length before name so server know how long it should be
read(4, socket); // Wait for AWK
send(playerName, socket, playerName.length());
read(4, socket); // Wait for AWK
int playerGuess;
int turn = 1;
bool correct = false;
cout << endl;
while (!correct) {
cout << "Turn: " << turn << endl;
cout << "Enter a guess: ";
playerGuess = getInput();
if (playerGuess > 9999 || playerGuess < 0) {
cout << "Guesses must be a number between 0000 and 9999!" << endl;
} else {
unsigned short guess = htons(short(playerGuess));
send(to_string(guess), socket, 100);
string resultOfGuess = read(101, socket); // Wait for AWK
int result = short(ntohs(stol(resultOfGuess)));
cout << "Result of guess: " << result << endl << endl;
if (result == 0) {
cout << "Congratulations! It took " << turn << " turns to guess the number!" << endl << endl;
correct = true;
} else {
turn++;
}
}
}
unsigned short turns = htons(short(turn));
send(to_string(turns), socket, 100);
// Logic to read the unformatted leader board from server
string leaderBoard = read(501, socket);
replace( leaderBoard.begin(), leaderBoard.end(), '&', '\n'); // Format for pretty printing.
string leaderBoardSans0 = remove_leading(leaderBoard, '0');
cout << "Leader board:\n";
cout << leaderBoardSans0;
close(socket);
}