-
Notifications
You must be signed in to change notification settings - Fork 26
Мурашкина: клиент клиента заказа еды для Швецовой #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
murfel
wants to merge
2
commits into
h31:master
Choose a base branch
from
ashvetNmurfel:eda_client
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| cmake_minimum_required(VERSION 3.12) | ||
| project(client) | ||
|
|
||
| set(CMAKE_CXX_STANDARD 17) | ||
|
|
||
| add_executable(client main.cpp) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| #include "client.h" | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| #ifndef CLIENT_CLIENT_H | ||
| #define CLIENT_CLIENT_H | ||
|
|
||
| #include <string> | ||
| #include <netdb.h> | ||
| #include <zconf.h> | ||
| #include <vector> | ||
| #include <fcntl.h> | ||
|
|
||
|
|
||
| int fd_set_blocking(int fd, int blocking) { | ||
| int flags = fcntl(fd, F_GETFL, 0); | ||
| if (flags == -1) | ||
| return 0; | ||
|
|
||
| if (blocking) | ||
| flags &= ~O_NONBLOCK; | ||
| else | ||
| flags |= O_NONBLOCK; | ||
| return fcntl(fd, F_SETFL, flags) != -1; | ||
| } | ||
|
|
||
|
|
||
| class client { | ||
| private: | ||
| int client_id_; | ||
| int sockfd_; | ||
|
|
||
| void write_header(int operation_type) { | ||
| write(sockfd_, (char *) &operation_type, sizeof(operation_type)); | ||
| write(sockfd_, (char *) &(this->client_id_), sizeof(this->client_id_)); | ||
| } | ||
|
|
||
| uint32_t read_uint32_t() { | ||
| uint32_t num; | ||
| read(sockfd_, (char *) & num, sizeof(num)); | ||
| return num; | ||
| } | ||
|
|
||
| std::string read_uint32_t_and_convert_to_string() { | ||
| return std::to_string(read_uint32_t()); | ||
| } | ||
|
|
||
| std::string read_create_order_response() { | ||
| return read_uint32_t_and_convert_to_string(); | ||
| } | ||
|
|
||
| std::string read_retrieve_history_response() { | ||
| uint32_t num_orders = read_uint32_t(); | ||
| std::string response = "Number of orders: " + std::to_string(num_orders) + "\n"; | ||
| for (int i = 0; i < num_orders; i++) { | ||
| uint32_t client_id = read_uint32_t(); | ||
| uint32_t shop_id = read_uint32_t(); | ||
| uint32_t num_goods = read_uint32_t(); | ||
|
|
||
| response += "Order #" + std::to_string(i) + ":\n"; | ||
| response += "Client ID: " + std::to_string(client_id) + ":\n"; | ||
| response += "Shop ID: " + std::to_string(shop_id) + ":\n"; | ||
| response += "Num goods: " + std::to_string(num_goods) + ":\n"; | ||
| response += "Goods numbers: "; | ||
| for (int j = 0; j < num_goods; j++) { | ||
| uint32_t good_id = read_uint32_t(); | ||
| response += std::to_string(good_id); | ||
| } | ||
| response += "\n\n"; | ||
| } | ||
| return response; | ||
| } | ||
|
|
||
| std::string read_add_shop_response() { | ||
| return read_uint32_t_and_convert_to_string(); | ||
| } | ||
|
|
||
| std::string read_disconnect_response() { | ||
| return ""; | ||
| } | ||
| public: | ||
| client(const std::string & hostname, int port, int client_id) : client_id_(client_id) { | ||
| struct hostent * host = gethostbyname(hostname.data()); | ||
| struct sockaddr_in serv_addr{}; | ||
| // Create socket. | ||
| sockfd_ = socket(AF_INET, SOCK_STREAM, 0); | ||
| if (sockfd_ < 0) { | ||
| perror("ERROR opening socket"); | ||
| exit(1); | ||
| } | ||
| // Validate host | ||
| if (host == nullptr) { | ||
| fprintf(stderr, "ERROR, no such host\n"); | ||
| exit(0); | ||
| } | ||
| bzero((char *) &serv_addr, sizeof(serv_addr)); | ||
| serv_addr.sin_family = AF_INET; | ||
| bcopy(host->h_addr, (char *) &serv_addr.sin_addr.s_addr, (size_t) host->h_length); | ||
| serv_addr.sin_port = htons(port); | ||
| } | ||
|
|
||
| std::string receive_incoming_event() { | ||
| fd_set_blocking(sockfd_, true); | ||
| int32_t type = 0; | ||
| ssize_t n = read(sockfd_, (char *) &type, sizeof(type)); | ||
| if (n == 0) | ||
| return {}; | ||
| fd_set_blocking(sockfd_, false); | ||
|
|
||
| switch (type) { | ||
| case 1: { | ||
| return read_create_order_response(); | ||
| } | ||
| case 2: { | ||
| return read_retrieve_history_response(); | ||
| } | ||
| case 3: { | ||
| return read_add_shop_response(); | ||
| } | ||
| case 4: { | ||
| return read_disconnect_response(); | ||
| } | ||
| default: { | ||
| return "Unknown response from the server."; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void create_order(int shop_id, const std::vector<int> & goods_ids) { | ||
| const int operation_type = 1; | ||
| this->write_header(operation_type); | ||
| write(sockfd_, (char *) & shop_id, sizeof(shop_id)); | ||
| int num_goods = goods_ids.size(); | ||
| write(sockfd_, (char *) & num_goods, sizeof(num_goods)); | ||
| for (int good_id : goods_ids) { | ||
| write(sockfd_, (char *) & good_id, sizeof(good_id)); | ||
| } | ||
| } | ||
|
|
||
| void retrieve_order_history() { | ||
| const int operation_type = 2; | ||
| this->write_header(operation_type); | ||
| } | ||
|
|
||
| void add_new_shop(const std::vector<int> & goods_ids, int zone_id) { | ||
| const int operation_type = 3; | ||
| this->write_header(operation_type); | ||
| int num_goods = goods_ids.size(); | ||
| write(sockfd_, (char *) & num_goods, sizeof(num_goods)); | ||
| for (int good_id : goods_ids) { | ||
| write(sockfd_, (char *) & good_id, sizeof(good_id)); | ||
| } | ||
| write(sockfd_, (char *) & zone_id, sizeof(zone_id)); | ||
| } | ||
|
|
||
| void disconnect() { | ||
| const int operation_type = 4; | ||
| this->write_header(operation_type); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| #endif //CLIENT_CLIENT_H | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| #include <iostream> | ||
| #include <string> | ||
| #include <vector> | ||
| #include "client.h" | ||
|
|
||
| void process_incoming_event(client *client1) { | ||
| std::string incoming_event = client1->receive_incoming_event(); | ||
| if (incoming_event.empty()) { | ||
| std::cout << "Server has disconnected. Bye!" << std::endl; | ||
| exit(0); | ||
| } | ||
| std::cout << client1->receive_incoming_event(); | ||
| } | ||
|
|
||
| int main(int argc, char * argv []) { | ||
| if (argc < 3) { | ||
| std::cout << "Usage: hostname port" << std::endl; | ||
| exit(1); | ||
| } | ||
|
|
||
| std::cout << "Please enter your client ID: "; | ||
| int client_id; | ||
| std::cin >> client_id; | ||
|
|
||
| client * client1 = new client(argv[0], atoi(argv[1]), client_id); | ||
|
|
||
| std::cout << "Connected to the food server" << std::endl; | ||
|
|
||
| #pragma clang diagnostic push | ||
| #pragma clang diagnostic ignored "-Wmissing-noreturn" | ||
| while (true) { | ||
| std::cout << "Please choose an action:" << std::endl; | ||
| std::cout << "[c]reate order" << std::endl; | ||
| std::cout << "[r]etrieve order history" << std::endl; | ||
| std::cout << "[a]dd a new shop" << std::endl; | ||
| std::cout << "[d]isconnect" << std::endl; | ||
|
|
||
| char input; | ||
| std::cin >> input; | ||
|
|
||
| switch (input) { | ||
| case 'c': { | ||
| std::cout << "Creating an order" << std::endl; | ||
| std::cout << "Please enter information in the following format: " | ||
| "shop_id num_goods goods_ids{num_goods}" << std::endl; | ||
| int shop_id; | ||
| int num_goods; | ||
| std::cin >> shop_id >> num_goods; | ||
| std::vector<int> goods_ids(num_goods); | ||
| for (int &good_id : goods_ids) { | ||
| std::cin >> good_id; | ||
| } | ||
| client1->create_order(shop_id, goods_ids); | ||
| process_incoming_event(client1); | ||
| break; | ||
| } | ||
| case 'r': { | ||
| std::cout << "Retrieving an order" << std::endl; | ||
| client1->retrieve_order_history(); | ||
| process_incoming_event(client1); | ||
| break; | ||
| } | ||
| case 'a': { | ||
| std::cout << "Adding a new shop" << std::endl; | ||
| std::cout << "Please enter information in the following format:" | ||
| "num_goods goods_ids{num_goods} zone_id" << std::endl; | ||
| int num_goods; | ||
| std::cin >> num_goods; | ||
| std::vector<int> goods_ids(num_goods); | ||
| for (int & good_id : goods_ids) { | ||
| std::cin >> good_id; | ||
| } | ||
| int zone_id; | ||
| std::cin >> zone_id; | ||
| client1->add_new_shop(goods_ids, zone_id); | ||
| process_incoming_event(client1); | ||
| break; | ||
| } | ||
| case 'd': { | ||
| std::cout << "Disconnecting. Bye!" << std::endl; | ||
| client1->disconnect(); | ||
| delete client1; | ||
| exit(0); | ||
| break; | ||
| } | ||
| default: { | ||
| std::cout << "Incorrect input: " << input << std::endl; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| } | ||
| #pragma clang diagnostic pop | ||
|
|
||
| return 0; | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#20 (comment)