From ee112553db4aa2ca224ea9b4dfe1d9793270f657 Mon Sep 17 00:00:00 2001 From: Tony Yang Date: Mon, 27 Dec 2021 04:45:11 +0800 Subject: [PATCH] [Feature] working client and server --- 109062273_cli.cpp | 112 +++++++++++++++++++++++++++++ 109062273_ser.cpp | 177 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) diff --git a/109062273_cli.cpp b/109062273_cli.cpp index e69de29..b0993b1 100644 --- a/109062273_cli.cpp +++ b/109062273_cli.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 256 +#define NOSERVER_RET 10 +#define INVALID_PORT_RET 20 +#define CONN_FAILED_RET 30 + +using namespace std; + +int main(int argc, char const *argv[]) { + // no server info specified + if (argc < 2) { + cerr << "No server info provided!" << endl << "Usage: client " << endl; + return NOSERVER_RET; + } + + int port = atoi(argv[2]); + if (port < 0 || port >= 65536) { + cerr << "Invalid port! port range: 0 ~ 65535" << endl; + return INVALID_PORT_RET; + } + + int sockfd = 0; + struct sockaddr_in info; + + // create tcp socket + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + cerr << "Failed to create socket." << endl; + } + + // setup server info + bzero(&info, sizeof(info)); + info.sin_family = PF_INET; + info.sin_addr.s_addr = inet_addr(argv[1]); + info.sin_port = htons(port); + + if (connect(sockfd, (struct sockaddr *) &info, sizeof(info)) == -1) { + cerr << "Connection failed." << endl; + return CONN_FAILED_RET; + } + + cout << "--------------" << endl; + cout << " Game start " << endl; + cout << "--------------" << endl; + + while (true) { + // ask for input + cout << "Guess: "; + string number; + cin >> number; + + // create payload + const char * msg = number.c_str(); + + #ifdef DEBUG + cout << msg << endl; + #endif + + if (send(sockfd, msg, sizeof(msg), 0) == -1) { + cerr << "Send error" << endl; + break; + }; + + // receive server response + char buffer[BUFFER_SIZE] = {0}; + int size = recv(sockfd, buffer, sizeof(buffer), 0); + if (size <= 0) { + cout << "Connection ended." << endl; + break; + } + + #ifdef DEBUG + cout << buffer << endl; + #endif + + // parse message from server + stringstream ss(buffer); + string lower, upper, count; + getline(ss, lower, ':'); + getline(ss, upper, ':'); + getline(ss, count, ':'); + + if (lower == upper) { + // win, start new turn + cout << "Answer Correct. Guessed for " << count << " times." << endl; + cout << endl; + cout << "--------------" << endl; + cout << " New Turn " << endl; + cout << "--------------" << endl; + continue; + } + + if (count != "0") { + cout << "Answer is fewer than " << upper << endl; + cout << "Answer is more than " << lower << endl; + } + + // space + cout << endl; + } + + return 0; +} \ No newline at end of file diff --git a/109062273_ser.cpp b/109062273_ser.cpp index e69de29..9ecb7ff 100644 --- a/109062273_ser.cpp +++ b/109062273_ser.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 256 +#define NOPORT_RET 10 +#define INVALID_PORT_RET 20 +#define BINDERR_RET 30 +#define LISTENERR_RET 35 + +using namespace std; + +class Game { + private: + int upper; + int lower; + int count; + int answer; + public: + Game(void) { + this->reset(); + } + + int get_upper() { + return this->upper; + } + + int get_lower() { + return this->lower; + } + + int get_count() { + return this->count; + } + + int get_answer() { + return this->answer; + } + + void reset() { + this->upper = 999; + this->lower = 0; + this->count = 0; + this->answer = rand() % 1000; + } + + bool guess(int num) { + this->count++; + if (num == answer) return true; + + if (num > answer && num < this->upper) this->upper = num; + else if (num < answer && num > this->lower) this->lower = num; + + return false; + } +}; + +int main(int argc, char const *argv[]) { + // initialize game + srand(time(nullptr)); + Game game; + + // no port specified + if (argc < 1) { + cerr << "No port provided!" << endl << "Usage: server " << endl; + return NOPORT_RET; + } + + int port = atoi(argv[1]); + if (port < 0 || port >= 65536) { + cerr << "Invalid port! port range: 0 ~ 65535" << endl; + return INVALID_PORT_RET; + } + + int sockfd = 0; + struct sockaddr_in server_info; + + // create tcp socket + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + cerr << "Failed to create socket" << endl; + } + + // setup server info + bzero((char *) &server_info, sizeof(server_info)); + server_info.sin_family = PF_INET; + server_info.sin_addr.s_addr = INADDR_ANY; + server_info.sin_port = htons(port); + + // bind + if (bind(sockfd, (struct sockaddr *) &server_info, sizeof(server_info)) == -1) { + cerr << "Cannot bind server." << endl; + return BINDERR_RET; + } + + // only one connection at the same time + if (listen(sockfd, 1) == -1) { + cerr << "Cannot listen socket." << endl; + return LISTENERR_RET; + } + cout << "Server up. Waiting connection..." << endl; + + int client_sockfd = 0; + struct sockaddr_in client_info; + socklen_t addrlen = sizeof(client_info); + + while (true) { + client_sockfd = accept(sockfd, (struct sockaddr *) &client_info, &addrlen); + if (client_sockfd < 0) { + cout << "Error occurred while handling request from client." << endl; + continue; + } + + // retrieve client info + char ip[INET_ADDRSTRLEN]; + uint16_t port; + inet_ntop(AF_INET, &client_info.sin_addr, ip, sizeof(ip)); + port = ntohs(client_info.sin_port); + + cout << "New client from " << ip << ":" << port << " has connected!" << endl; + + // reset for new client + game.reset(); + + while (true) { + // clear buffer for receive message + char buffer[BUFFER_SIZE]; + memset(buffer, 0, sizeof(buffer)); + + // wait message + if (recv(client_sockfd, buffer, sizeof(buffer), 0) <= 0) { + // closed connection + cout << "Disconnected." << endl; + break; + } + + int guess = atoi(buffer); + + #ifdef DEBUG + cout << guess << endl; + #endif + + // message + stringstream ss; + const char * msg; + + #ifdef DEBUG + cout << msg << endl; + #endif + + // generate payload + if (game.guess(guess)) { + // win + ss << game.get_answer() << ":" << game.get_answer() << ":" << game.get_count(); + + // new turn for this client + game.reset(); + } else { + ss << game.get_lower() << ":" << game.get_upper() << ":" << game.get_count(); + } + + msg = ss.str().c_str(); + + // send to client + send(client_sockfd, msg, strlen(msg), 0); + } + } + + return 0; +} \ No newline at end of file