Endil

cn-lab5-client

Dec 18th, 2015
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.75 KB | None | 0 0
  1. // cn-lab5-client.cpp: определяет точку входа для консольного приложения.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #define _WINSOCK_DEPRECATED_NO_WARNINGS
  6. #include <chrono>
  7. #include <condition_variable>
  8. #include <iostream>
  9. #include <map>
  10. #include <regex>
  11. #include <string>
  12. #include <thread>
  13. #include <winsock2.h>
  14.  
  15. #pragma comment(lib, "ws2_32.lib")
  16.  
  17. using namespace std;
  18. using namespace std::chrono;
  19.  
  20. typedef unsigned long long ull;
  21.  
  22. mutex m;
  23. condition_variable cvar;
  24. bool cvar_backup;
  25.  
  26. class Network {
  27. private:
  28.     SOCKET sock;
  29.     sockaddr_in server_addr;
  30. public:
  31.     Network() {
  32.         WSAData wsadata;
  33.         WSAStartup(0x0202, &wsadata);
  34.     }
  35.     ~Network() {
  36.         WSACleanup();
  37.     }
  38.     void connect(const string &ip_addr, const int &port) {
  39.         sock = socket(AF_INET, SOCK_STREAM, 0);
  40.         sockaddr_in server_addr;
  41.         server_addr.sin_family = AF_INET;
  42.         server_addr.sin_addr.S_un.S_addr = inet_addr(ip_addr.c_str());
  43.         server_addr.sin_port = htons(port);
  44.         int ret = ::connect(sock, (sockaddr *)&server_addr, sizeof(server_addr));
  45.         if (ret == INVALID_SOCKET) {
  46.             throw exception("&wsa_error_connect");
  47.             return;
  48.         }
  49.     }
  50.     void disconnect() {
  51.         closesocket(sock);
  52.     }
  53.     void send(const string &s) const {
  54.         ::send(sock, s.c_str(), s.length(), 0);
  55.     }
  56.     string receive() const {
  57.         char recv_buff[65536];
  58.         int len = recv(sock, &recv_buff[0], sizeof(recv_buff) - 1, 0);
  59.         if (len == -1)
  60.             throw exception("&wsa_error_recv");
  61.         recv_buff[len] = 0;
  62.         return recv_buff;
  63.     }
  64. }network;
  65.  
  66. string tp_to_str(const system_clock::time_point &tp) {
  67.     return to_string(time_point_cast<milliseconds>(tp).time_since_epoch().count());
  68. }
  69.  
  70. class Commands {
  71.     map<string, string> except_list = { {"&invalid_syntax", "Invalid syntax"} };
  72. private:
  73.     map<string, void(Commands::*)(const smatch &) const> command_list;
  74.     void sms(const smatch &input) const {
  75.         auto tp = system_clock::now();
  76.         regex pattern(R"(\-d|(\+?[0-9]+))");
  77.         if (!regex_match(input.str(2), pattern))
  78.             throw exception("&invalid_syntax");
  79.         network.send(tp_to_str(tp) + " " + input.str(0));
  80.     }
  81.     void del(const smatch &input) const {
  82.         auto tp = system_clock::now();
  83.         regex pattern(R"(\+?[0-9]+)");
  84.         if (!regex_match(input.str(2), pattern))
  85.             throw exception("&invalid_syntax");
  86.         network.send(tp_to_str(tp) + " " + input.str(0));
  87.     }
  88.     void exit(const smatch &input) const {
  89.         network.send("&client_exit");
  90.         cvar_backup = true;
  91.         cvar.notify_one();
  92.     }
  93. public:
  94.     Commands() {
  95.         command_list.emplace("exit", &Commands::exit);
  96.         command_list.emplace("quit", &Commands::exit);
  97.         command_list.emplace("sms", &Commands::sms);
  98.         command_list.emplace("del", &Commands::del);
  99.     }
  100.     void exec(const smatch &input) const {             
  101.         try {
  102.             (this->*command_list.at(input.str(1)))(input);
  103.         }
  104.         catch (exception e) {
  105.             cout << except_list.at(e.what()) << endl;
  106.         }
  107.     }
  108. }commands;
  109.  
  110. void user_input() {
  111.     cout << "Enter your phone number: " << endl;
  112.     string num;
  113.     regex pattern(R"(\+?[0-9]+)");
  114.     while (true) {
  115.         getline(cin, num);
  116.         if (regex_match(num, pattern))
  117.             break;
  118.         cout << "Invalid number" << endl;
  119.     }
  120.     network.send(num);
  121.     while (true) {
  122.         string s;
  123.         getline(cin, s);
  124.         if (s == "exit") {
  125.             cvar_backup = true;
  126.             cvar.notify_one();
  127.             return;
  128.         }
  129.         regex pattern(R"(^(".+"|[.\S]+)\s*(".*"|[.\S]*)\s*(".*"|[.\S]*)\s*(".*"|[.\S]*)\s*$)");
  130.         smatch match_results;
  131.         regex_match(s, match_results, pattern);
  132.         commands.exec(match_results);
  133.     }
  134. }
  135.  
  136. map<string, string> wsa_except_list = { { "&wsa_error_accept", "accept error " },
  137.                                         { "&wsa_error_recv", "recv error " } };
  138.  
  139. void port_listen() {
  140.     map<string, string> ans_list = { { "&server_stop", "Server was stopped. Type \"exit\" to exit." },
  141.                                      { "&sms_success", "Message sent successfully" },
  142.                                      { "&del_success", "Message deleted successfully" },
  143.                                      { "&del_fail_too_late", "Message was sent more than a minute ago" },
  144.                                      { "&del_fail_not_deletable", "Message wasn't marked as deletable" },
  145.                                      { "&del_fail_no_such_addressee", "You haven't sent any messages to this number yet" } };
  146.     while (true) {
  147.         string ans;
  148.         try {
  149.             ans = network.receive();
  150.         }
  151.         catch (exception e) {
  152.             int wsa_error = WSAGetLastError();
  153.             if (wsa_error != 0) {
  154.                 cout << wsa_except_list.at(e.what()) << wsa_error << endl;
  155.             }
  156.             return;
  157.         }
  158.         cout << ans_list.at(ans) << endl;
  159.     }
  160. }
  161.  
  162. int main()
  163. {
  164.     try {
  165.         network.connect("127.0.0.1", 5005);
  166.     }
  167.     catch (exception e) {
  168.         cout << "Server is unreachable" << endl;
  169.         return 1;
  170.     }
  171.     thread listen(port_listen);
  172.     thread input(user_input);
  173.     unique_lock<mutex> locked(m);
  174.     cvar.wait(locked, [] {return cvar_backup; });
  175.  
  176.     network.disconnect();
  177.     if (input.joinable())
  178.         input.join();
  179.     if (listen.joinable())
  180.         listen.join();
  181.     return 0;
  182. }
Advertisement
Add Comment
Please, Sign In to add comment