Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // cn-lab5-server.cpp: определяет точку входа для консольного приложения.
- //
- #include "stdafx.h"
- #include <chrono>
- #include <iostream>
- #include <map>
- #include <regex>
- #include <set>
- #include <sstream>
- #include <string>
- #include <thread>
- #include <vector>
- #include <winsock2.h>
- #pragma comment(lib, "ws2_32.lib")
- using namespace std;
- using namespace std::chrono;
- typedef long long ll;
- typedef unsigned long long ull;
- typedef time_point<system_clock, milliseconds> timepoint;
- vector<thread> connected_clients_list;
- timepoint str_to_tp(string _tp) {
- milliseconds tp_m(stoull(_tp));
- timepoint tp(tp_m);
- return tp;
- }
- class Message {
- private:
- timepoint tp;
- string dest_number;
- string text;
- bool deletable;
- public:
- Message(timepoint _tp, string _dest_number, string _text, bool _deletable) {
- tp = _tp;
- dest_number = _dest_number;
- text = _text;
- deletable = _deletable;
- }
- string get_dest_number() {
- return dest_number;
- }
- bool is_deletable() {
- return deletable;
- }
- timepoint get_tp() {
- return tp;
- }
- };
- class MessageList {
- private:
- vector<Message> messages;
- public:
- int add(string _tp, string _dest_number, string _text, bool _deletable = false) {
- timepoint tp = str_to_tp(_tp);
- messages.emplace_back(tp, _dest_number, _text, _deletable);
- return 0;
- }
- int remove(string _timepoint, string _dest_number) {
- for (auto i = messages.rbegin(); i != messages.rend(); i++)
- if (i->get_dest_number() == _dest_number) {
- if (i->is_deletable() == true) {
- timepoint tp = str_to_tp(_timepoint);
- milliseconds period(60000);
- if (duration_cast<milliseconds>(tp - i->get_tp()) <= period) {
- messages.erase(next(i).base());
- return 0;
- }
- throw exception("&del_fail_too_late");
- }
- throw exception("&del_fail_not_deletable");
- }
- throw exception("&del_fail_no_such_addressee");
- }
- };
- map<string, MessageList> client_message_list;
- class Network {
- private:
- SOCKET main_sock;
- map<string, pair<sockaddr_in, SOCKET>> client_list;
- string receive(SOCKET sock) {
- char recv_buff[65536];
- int len = recv(sock, &recv_buff[0], sizeof(recv_buff) - 1, 0);
- if (len == -1)
- return "";
- recv_buff[len] = 0;
- string s = recv_buff;
- return s;
- }
- public:
- Network() {
- WSAData wsadata;
- WSAStartup(0x0202, &wsadata);
- cout << "WinSock2 initialized" << endl;
- }
- ~Network() {
- WSACleanup();
- }
- int start(int port) {
- main_sock = socket(AF_INET, SOCK_STREAM, 0);
- cout << "Main socket created successfully" << endl;
- sockaddr_in addr_local;
- addr_local.sin_family = AF_INET;
- addr_local.sin_addr.S_un.S_addr = 0;
- addr_local.sin_port = htons(port);
- ::bind(main_sock, (sockaddr *)&addr_local, sizeof(addr_local));
- cout << "Port " << ntohs(addr_local.sin_port) << " bound successful" << endl;
- listen(main_sock, SOMAXCONN);
- cout << "Listening port 5005" << endl;
- return 0;
- }
- int stop() {
- for (auto pair : client_list) {
- send(pair.first, "&server_stop");
- closesocket(pair.second.second);
- }
- closesocket(main_sock);
- return 0;
- }
- int send(string num, string s) {
- ::send(client_list.at(num).second, s.c_str(), s.length(), 0);
- return 0;
- }
- string receive(string num) {
- char recv_buff[65536];
- int len = recv(client_list.at(num).second, &recv_buff[0], sizeof(recv_buff) - 1, 0);
- if (len == -1)
- return "";
- recv_buff[len] = 0;
- string s = recv_buff;
- return s;
- }
- string accept() {
- sockaddr_in client_addr;
- int client_addr_size = sizeof(client_addr);
- SOCKET client_sock = ::accept(main_sock, (sockaddr *)&client_addr, &client_addr_size);
- if (client_sock == INVALID_SOCKET) {
- int wsa_error = WSAGetLastError();
- if (wsa_error != 10004)
- cout << "Accept error " << wsa_error << endl;
- return "";
- }
- string num = receive(client_sock);
- cout << num << " connected" << endl;
- client_list.try_emplace(num, make_pair(client_addr, client_sock));
- return num;
- }
- }network;
- class Commands {
- private:
- map<string, int(Commands::*)(smatch, string)> command_list;
- int sms(smatch input, string num) {
- if (input.str(3) == "-d") {
- client_message_list.at(input.str(4)).add(input.str(1), input.str(4), input.str(5), true);
- cout << num << " sent a message to " << input.str(4);
- }
- else {
- client_message_list.at(input.str(3)).add(input.str(1), input.str(3), input.str(4));
- cout << num << " sent a message to " << input.str(3);
- }
- network.send(input.str(3), "&sms_success");
- return 0;
- }
- int del(smatch input, string num) {
- try {
- client_message_list.at(input.str(3)).remove(input.str(1), input.str(2));
- }
- catch (exception e) {
- cout << "Deleting message from " << num << " to " << input.str(2) << " throw an exception: " << e.what() << endl;
- network.send(num, e.what());
- }
- cout << "Deleting message from " << num << " to " << input.str(2) << " was successful" << endl;
- network.send(num, "&del_success");
- return 0;
- }
- public:
- Commands() {
- command_list.emplace("sms", &Commands::sms);
- command_list.emplace("del", &Commands::del);
- }
- int exec(smatch input, string num) {
- (this->*command_list.at(input.str(2)))(input, num);
- return 0;
- }
- }commands;
- int client_process(string num) {
- client_message_list.try_emplace(num);
- while (true) {
- string s = network.receive(num);
- if (s == "")
- break;
- regex pattern(R"(^(\d+)\s(".+"|[.\S]+)\s*(".*"|[.\S]*)\s*(".*"|[.\S]*)\s*(".*"|[.\S]*)\s*$)");
- smatch match_results;
- regex_match(s, match_results, pattern);
- commands.exec(match_results, num);
- }
- cout << num << " disconnected" << endl;
- return 0;
- }
- int port_listen() {
- while (true) {
- string num = network.accept();
- connected_clients_list.emplace_back(client_process, num);
- }
- return 0;
- }
- int main()
- {
- cout << "cn-lab5 var10 server was started" << endl;
- network.start(5005);
- thread listen(port_listen);
- string s;
- do {
- cin >> s;
- } while (s != "stop" && s != "exit");
- network.stop();
- if (listen.joinable())
- listen.join();
- for (auto i = 0; i < connected_clients_list.size(); i++)
- if (connected_clients_list.at(i).joinable())
- connected_clients_list.at(i).join();
- network.~Network();
- cout << "cn-lab5 var10 server was stopped" << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement