From 550cf32e27d448ee1aa5a01ab9c221cc49548470 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Mon, 5 Sep 2022 16:40:50 +0300 Subject: [PATCH 1/5] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80,=20?= =?UTF-8?q?=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?chat()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lesson_03/ap/ap.cpp | 136 +++++++++++++++++++++++++++++++++++ lesson_03/ap/ap.hpp | 68 ++++++++++++++++++ lesson_03/header/address.hpp | 28 ++++++++ lesson_03/header/server.hpp | 65 +++++++++++++++++ lesson_03/header/socket.hpp | 26 +++++++ lesson_03/main.cpp | 32 +++++++++ lesson_03/source/address.cpp | 44 ++++++++++++ lesson_03/source/server.cpp | 113 +++++++++++++++++++++++++++++ lesson_03/source/socket.cpp | 32 +++++++++ 9 files changed, 544 insertions(+) create mode 100644 lesson_03/ap/ap.cpp create mode 100644 lesson_03/ap/ap.hpp create mode 100644 lesson_03/header/address.hpp create mode 100644 lesson_03/header/server.hpp create mode 100644 lesson_03/header/socket.hpp create mode 100644 lesson_03/main.cpp create mode 100644 lesson_03/source/address.cpp create mode 100644 lesson_03/source/server.cpp create mode 100644 lesson_03/source/socket.cpp diff --git a/lesson_03/ap/ap.cpp b/lesson_03/ap/ap.cpp new file mode 100644 index 0000000..b385274 --- /dev/null +++ b/lesson_03/ap/ap.cpp @@ -0,0 +1,136 @@ +/* + * ap.cpp + * + * Created on: 05 сен. 2022 г. + * Author: alexander + */ + +#include + +namespace ap +{ + +ConfigOption::ConfigOption(const std::string &longParameter, const char shortParameter, const hasArg ha) : + _longParameter(nullptr), _shortParameter(shortParameter), _ha(ha) +{ + _longParameter = new char[longParameter.length() + 1]; + strcpy(_longParameter, longParameter.c_str()); +} + +const char* ConfigOption::getLongParameter() const +{ + return _longParameter; +} + +const char& ConfigOption::getShortParameter() const +{ + return _shortParameter; +} + +const hasArg& ConfigOption::getPresenceArgument() const +{ + return _ha; +} + +Option::Option() : _set(false) +{ +} + +void Option::set() +{ + _set = true; +} + +void Option::push(const std::string &value) +{ + _values.push_back(value); +} + +std::vector& Option::getValues() +{ + return _values; +} + +bool Option::isSet() const +{ + return _set; +} + +void Hub::_createArguments(const std::vector &options, bool silence) +{ + _longOptions = new struct option[options.size() + 1]; + _sizeOptions = options.size(); + std::string temp; + if (silence) + temp.push_back(':'); + for (auto const &opt : options | boost::adaptors::indexed(0)) + { + _longOptions[opt.index()].name = opt.value().getLongParameter(); + _longOptions[opt.index()].has_arg = opt.value().getPresenceArgument(); + _longOptions[opt.index()].flag = nullptr; + _longOptions[opt.index()].val = opt.value().getShortParameter(); + + temp.push_back(opt.value().getShortParameter()); + switch (opt.value().getPresenceArgument()) + { + case hasArg::OPTIONAL: + temp.push_back(':'); + /* no break */ + case hasArg::REQUIRED: + temp.push_back(':'); + break; + case hasArg::NO: + break; + } + + _arguments[opt.value().getShortParameter()].first = false; + } + + _longOptions[options.size()].name = nullptr; + _longOptions[options.size()].has_arg = 0; + _longOptions[options.size()].flag = nullptr; + _longOptions[options.size()].val = 0; + + _shortOptions = new char[temp.size() + 1]; + strcpy(_shortOptions, temp.c_str()); +} + +Hub::Hub(const std::vector &options, bool silence) : + _longOptions(nullptr), _shortOptions(nullptr) +{ + _createArguments(options, silence); +} + +void Hub::readArguments(int argc, char *argv[], void (*_callback)()) +{ + int next_option; + while ((next_option = getopt_long(argc, argv, _shortOptions, _longOptions, nullptr)) != -1) + { + if (_arguments.count(next_option)) + { + _arguments[next_option].first = true; + _arguments[next_option].second.set(); + if (optarg) + _arguments[next_option].second.push(std::string(optarg)); + } + if (next_option == '?' && _callback) + _callback(); + } +} + +Option Hub::getOption(char key) const +{ + return _arguments.count(key) && _arguments.at(key).first ? _arguments.at(key).second : Option(); +} + +Hub::~Hub() +{ + delete[] _shortOptions; + for (size_t i = 0; i < _sizeOptions; ++i) + { + delete[] _longOptions[i].name; + } + delete[] _longOptions; +} + +} diff --git a/lesson_03/ap/ap.hpp b/lesson_03/ap/ap.hpp new file mode 100644 index 0000000..8ae0de8 --- /dev/null +++ b/lesson_03/ap/ap.hpp @@ -0,0 +1,68 @@ +/* + * ap.hpp + * + * Created on: 05 сен. 2022 г. + * Author: alexander + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ap +{ + +enum hasArg +{ + NO, REQUIRED, OPTIONAL +}; + +typedef std::vector (*_handler)(const std::vector&); + +class ConfigOption +{ +private: + char *_longParameter; + const char _shortParameter; + const hasArg _ha; +public: + ConfigOption(const std::string &longParameter, const char shortParameter, const hasArg ha); + const char* getLongParameter() const; + const char& getShortParameter() const; + const hasArg& getPresenceArgument() const; +}; + +class Option +{ +private: + std::vector _values; + bool _set; +public: + Option(); + void push(const std::string &value); + std::vector& getValues(); + void set(); + bool isSet() const; +}; + +class Hub +{ +private: + struct option *_longOptions; + size_t _sizeOptions; + char *_shortOptions; + std::map> _arguments; + void _createArguments(const std::vector &options, bool silence); +public: + Hub(const std::vector &options, bool silence = true); + void readArguments(int argc, char *argv[], void (*_callback)() = nullptr); + Option getOption(char key) const; + ~Hub(); +}; + +} diff --git a/lesson_03/header/address.hpp b/lesson_03/header/address.hpp new file mode 100644 index 0000000..4fdf301 --- /dev/null +++ b/lesson_03/header/address.hpp @@ -0,0 +1,28 @@ +/* + * address.hpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#pragma once + +#include +#include + +namespace zh { + +class Address +{ +private: + struct sockaddr_in _addr; + unsigned int _len; +public: + Address(); + Address(const Address &address); + Address(const unsigned short int family, const unsigned int addr, const unsigned short int port); + unsigned int& size(); + struct sockaddr_in& operator*(); +}; + +} diff --git a/lesson_03/header/server.hpp b/lesson_03/header/server.hpp new file mode 100644 index 0000000..5b1f24c --- /dev/null +++ b/lesson_03/header/server.hpp @@ -0,0 +1,65 @@ +/* + * server.hpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#pragma once + +//#include + +#include +#include +#include +#include +#include + +namespace zh +{ + +class Server // @suppress("Class has a virtual method and non-virtual destructor") +{ +protected: + std::unique_ptr _socket; + std::unique_ptr
_local, _client; + unsigned int _sizeClient; + const unsigned short int _port; + int _connfd; +public: + Server(const unsigned short int port); + virtual void bind() = 0; + virtual void listen() = 0; +}; + +typedef void (*hook)(std::string buffer, Server &s); + +class ServerTCP: public Server // @suppress("Class has a virtual method and non-virtual destructor") +{ +private: + bool _bind; + const unsigned short int _sizeBuffer; + std::unique_ptr _buffer; + + class Hook + { + private: + std::string _command; + hook _handler; + public: + Hook(std::string command, hook handler); + void execute(std::string buffer, Server &s); + }; + + std::vector _hooks; + + void chat(); +public: + ServerTCP(const unsigned short int port, const unsigned short int sizeBuffer = 1024); + void bind(); + void listen(); + void registerHook(std::string command, hook handler); +}; + +} + diff --git a/lesson_03/header/socket.hpp b/lesson_03/header/socket.hpp new file mode 100644 index 0000000..4e29363 --- /dev/null +++ b/lesson_03/header/socket.hpp @@ -0,0 +1,26 @@ +/* + * socket.hpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#pragma once + +#include +#include +#include + +namespace zh { + +class Socket +{ +private: + int _sockfd; +public: + Socket(const int domain, const int type, const int protocol); + operator int() const; + ~Socket(); +}; + +} diff --git a/lesson_03/main.cpp b/lesson_03/main.cpp new file mode 100644 index 0000000..cf64aad --- /dev/null +++ b/lesson_03/main.cpp @@ -0,0 +1,32 @@ +/* + * main.cpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + ap::Hub hub({{ "port", 'p', ap::REQUIRED }}); + hub.readArguments(argc, argv); + + auto optionPort = hub.getOption('p'); + if (!optionPort.isSet()) + { + std::cerr << "Порт не был установлен!" << std::endl; + exit(EXIT_FAILURE); + } + + int port = std::stoi(optionPort.getValues()[0]); + + zh::ServerTCP tcpServer(port); + tcpServer.bind(); + tcpServer.listen(); + + return 0; +} diff --git a/lesson_03/source/address.cpp b/lesson_03/source/address.cpp new file mode 100644 index 0000000..132fa77 --- /dev/null +++ b/lesson_03/source/address.cpp @@ -0,0 +1,44 @@ +/* + * address.cpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#include + +namespace zh { + +Address::Address() +{ + memset(&_addr, 0, sizeof(_addr)); + _len = sizeof(_addr); +} + +Address::Address(const Address &address) +{ + _addr = address._addr; + _len = address._len; +} + +Address::Address(const unsigned short int family, const unsigned int addr, const unsigned short int port) +{ + memset(&_addr, 0, sizeof(_addr)); + _len = sizeof(_addr); + + _addr.sin_family = family; + _addr.sin_addr.s_addr = htonl(addr); + _addr.sin_port = htons(port); +} + +unsigned int& Address::size() +{ + return _len; +} + +struct sockaddr_in& Address::operator*() +{ + return _addr; +} + +} diff --git a/lesson_03/source/server.cpp b/lesson_03/source/server.cpp new file mode 100644 index 0000000..9872b01 --- /dev/null +++ b/lesson_03/source/server.cpp @@ -0,0 +1,113 @@ +/* + * server.cpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#include +#include +#include + +namespace zh +{ + +#define MAX 1024 + +Server::Server(const unsigned short int port) : _port(port), _connfd(-1) +{ + _sizeClient = sizeof(*_client); +} + +ServerTCP::Hook::Hook(std::string command, hook handler) : _command(command), _handler(handler) +{ +} + +void ServerTCP::Hook::execute(std::string buffer, Server &s) +{ + if (_command == "") + { + _handler(buffer, s); + } + else + { + auto pos = buffer.find_first_of(_command); + if (pos != std::string::npos && pos == 0) + { + _handler(buffer, s); + } + } +} + +void ServerTCP::registerHook(std::string command, hook handler) +{ + _hooks.push_back({ command, handler }); +} + +ServerTCP::ServerTCP(const unsigned short int port, const unsigned short int sizeBuffer) : Server(port), _bind(false), _sizeBuffer(sizeBuffer) +{ + _socket = std::make_unique(AF_INET, SOCK_STREAM, IPPROTO_IP); + _local = std::make_unique
(AF_INET, INADDR_ANY, port); + _buffer = std::make_unique(sizeBuffer); +} + +void ServerTCP::bind() +{ + if (_bind) + { + std::cerr << "Адрес уже связан с дескриптором слушающего сокета!" << std::endl; + return; + } + + if (::bind((*_socket), reinterpret_cast(&(*_local)), (*_local).size()) != 0) + std::cerr << "Не удаётся связать адрес с дескриптором слушающего сокета!" << std::endl; + else + _bind = true; +} + +void ServerTCP::listen() +{ + if (::listen(*_socket, 0) != 0) + { + std::cerr << "Не удаётся создать очередь соединений для сокета!" << std::endl; + return; + } + + while (_bind) + { + if ((_connfd = ::accept(*_socket, reinterpret_cast(&(*_client)), &_sizeClient)) < 0) + { + std::cerr << "Не удаётся верифицировать и принять пакеты от клиента!" << std::endl; + return; + } + + // Обработка соединения с клиентом + chat(); + } +} + +void ServerTCP::chat() +{ +// char buff[MAX]; +// int n; + while (true) + { +// bzero(buff, sizeof(buff)); +// printf("Enter the string : "); +// n = 0; +// while ((buff[n++] = getchar()) != '\n') +// ; +// write(_connfd, buff, sizeof(buff)); + bzero(_buffer.get(), _sizeBuffer); + read(_connfd, _buffer.get(), _sizeBuffer); + std::cout << _buffer.get() << std::endl; +// printf("From Server : %s", *_buffer); +// if ((strncmp((*_buffer), "exit", 4)) == 0) +// { +// printf("Client Exit...\n"); +// break; +// } + } +} + +} diff --git a/lesson_03/source/socket.cpp b/lesson_03/source/socket.cpp new file mode 100644 index 0000000..ccfe2a2 --- /dev/null +++ b/lesson_03/source/socket.cpp @@ -0,0 +1,32 @@ +/* + * socket.cpp + * + * Created on: 5 сент. 2022 г. + * Author: alexander + */ + +#include +#include + +namespace zh { + +Socket::Socket(const int domain, const int type, const int protocol) +{ + if ((_sockfd = socket(domain, type, protocol)) < 0) + { + perror("socket creation failed"); + exit(EXIT_FAILURE); + } +} + +Socket::operator int() const +{ + return _sockfd; +} + +Socket::~Socket() +{ + ::close(_sockfd); +} + +} -- 2.40.1 From 1bcbee1c36fd4f0cfcbb7444494ebd3e3525bac9 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Tue, 6 Sep 2022 17:21:06 +0300 Subject: [PATCH 2/5] =?UTF-8?q?=D0=9F=D0=BE=D0=B1=D0=B0=D0=B9=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B5=20=D1=87=D1=82=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B2=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20chat()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lesson_03/header/server.hpp | 3 ++- lesson_03/source/server.cpp | 30 +++++++++++------------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/lesson_03/header/server.hpp b/lesson_03/header/server.hpp index 5b1f24c..9611474 100644 --- a/lesson_03/header/server.hpp +++ b/lesson_03/header/server.hpp @@ -39,7 +39,7 @@ class ServerTCP: public Server // @suppress("Class has a virtual method and non- private: bool _bind; const unsigned short int _sizeBuffer; - std::unique_ptr _buffer; + std::unique_ptr _buffer; class Hook { @@ -54,6 +54,7 @@ private: std::vector _hooks; void chat(); + void readData(const int sizeData); public: ServerTCP(const unsigned short int port, const unsigned short int sizeBuffer = 1024); void bind(); diff --git a/lesson_03/source/server.cpp b/lesson_03/source/server.cpp index 9872b01..40fd8f8 100644 --- a/lesson_03/source/server.cpp +++ b/lesson_03/source/server.cpp @@ -8,12 +8,11 @@ #include #include #include +#include namespace zh { -#define MAX 1024 - Server::Server(const unsigned short int port) : _port(port), _connfd(-1) { _sizeClient = sizeof(*_client); @@ -48,7 +47,7 @@ ServerTCP::ServerTCP(const unsigned short int port, const unsigned short int siz { _socket = std::make_unique(AF_INET, SOCK_STREAM, IPPROTO_IP); _local = std::make_unique
(AF_INET, INADDR_ANY, port); - _buffer = std::make_unique(sizeBuffer); + _buffer = std::make_unique(sizeBuffer); } void ServerTCP::bind() @@ -86,27 +85,20 @@ void ServerTCP::listen() } } +void ServerTCP::readData(const int sizeData) +{ + +} + void ServerTCP::chat() { -// char buff[MAX]; -// int n; while (true) { -// bzero(buff, sizeof(buff)); -// printf("Enter the string : "); -// n = 0; -// while ((buff[n++] = getchar()) != '\n') -// ; -// write(_connfd, buff, sizeof(buff)); bzero(_buffer.get(), _sizeBuffer); - read(_connfd, _buffer.get(), _sizeBuffer); - std::cout << _buffer.get() << std::endl; -// printf("From Server : %s", *_buffer); -// if ((strncmp((*_buffer), "exit", 4)) == 0) -// { -// printf("Client Exit...\n"); -// break; -// } + read(_connfd, _buffer.get(), 4); + std::cout << *reinterpret_cast(_buffer.get()) << std::endl; + close(_connfd); + break; } } -- 2.40.1 From 402c3f865f432e411d011cd8ae790aac4df198cf Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Wed, 7 Sep 2022 15:43:34 +0300 Subject: [PATCH 3/5] =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=20+=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lesson_03/header/address.hpp | 5 ++++ lesson_03/header/buffer.hpp | 28 +++++++++++++++++++ lesson_03/header/client.hpp | 27 +++++++++++++++++++ lesson_03/header/server.hpp | 33 ++++++++--------------- lesson_03/header/stock.hpp | 31 +++++++++++++++++++++ lesson_03/main.cpp | 48 ++++++++++++++++++++++++++++++--- lesson_03/source/address.cpp | 12 +++++++++ lesson_03/source/buffer.cpp | 40 +++++++++++++++++++++++++++ lesson_03/source/client.cpp | 50 ++++++++++++++++++++++++++++++++++ lesson_03/source/server.cpp | 52 +++++++++++++++++++++--------------- lesson_03/source/stock.cpp | 18 +++++++++++++ 11 files changed, 297 insertions(+), 47 deletions(-) create mode 100644 lesson_03/header/buffer.hpp create mode 100644 lesson_03/header/client.hpp create mode 100644 lesson_03/header/stock.hpp create mode 100644 lesson_03/source/buffer.cpp create mode 100644 lesson_03/source/client.cpp create mode 100644 lesson_03/source/stock.cpp diff --git a/lesson_03/header/address.hpp b/lesson_03/header/address.hpp index 4fdf301..99f2772 100644 --- a/lesson_03/header/address.hpp +++ b/lesson_03/header/address.hpp @@ -9,6 +9,9 @@ #include #include +#include +#include +#include namespace zh { @@ -16,11 +19,13 @@ class Address { private: struct sockaddr_in _addr; + std::unique_ptr _host; unsigned int _len; public: Address(); Address(const Address &address); Address(const unsigned short int family, const unsigned int addr, const unsigned short int port); + Address(const unsigned short int family, const std::string &addr, const unsigned short int port); unsigned int& size(); struct sockaddr_in& operator*(); }; diff --git a/lesson_03/header/buffer.hpp b/lesson_03/header/buffer.hpp new file mode 100644 index 0000000..208bd7b --- /dev/null +++ b/lesson_03/header/buffer.hpp @@ -0,0 +1,28 @@ +/* + * buffer.hpp + * + * Created on: 7 сент. 2022 г. + * Author: alexander + */ + +#pragma once + +#include + +namespace zh +{ + +class Buffer +{ +private: + const unsigned short int _size; + std::unique_ptr _buffer; +public: + Buffer(const unsigned short int size); + const unsigned short int getSize() const; + const std::string getString() const; + void clear(); + operator void*(); +}; + +} diff --git a/lesson_03/header/client.hpp b/lesson_03/header/client.hpp new file mode 100644 index 0000000..08ec0a0 --- /dev/null +++ b/lesson_03/header/client.hpp @@ -0,0 +1,27 @@ +/* + * client.hpp + * + * Created on: 7 сент. 2022 г. + * Author: alexander + */ + +#pragma once + +#include + +namespace zh +{ + +class ClientTCP: public Server // @suppress("Class has a virtual method and non-virtual destructor") +{ +private: + bool _connect; + int _connfd; + + void chat(); +public: + ClientTCP(const std::string &address, const unsigned short int port, const unsigned short int sizeBuffer = 1024); + void connect(); +}; + +} diff --git a/lesson_03/header/server.hpp b/lesson_03/header/server.hpp index 9611474..5c7f012 100644 --- a/lesson_03/header/server.hpp +++ b/lesson_03/header/server.hpp @@ -9,37 +9,25 @@ //#include -#include -#include -#include +#include #include #include namespace zh { -class Server // @suppress("Class has a virtual method and non-virtual destructor") -{ -protected: - std::unique_ptr _socket; - std::unique_ptr
_local, _client; - unsigned int _sizeClient; - const unsigned short int _port; - int _connfd; -public: - Server(const unsigned short int port); - virtual void bind() = 0; - virtual void listen() = 0; -}; +class ServerTCP; -typedef void (*hook)(std::string buffer, Server &s); +typedef void (*hook)(std::string buffer, ServerTCP &s); class ServerTCP: public Server // @suppress("Class has a virtual method and non-virtual destructor") { private: bool _bind; - const unsigned short int _sizeBuffer; - std::unique_ptr _buffer; + int _connfd; + bool _listenLoop; + unsigned int _sizeClient; + std::unique_ptr
_client; class Hook { @@ -48,18 +36,19 @@ private: hook _handler; public: Hook(std::string command, hook handler); - void execute(std::string buffer, Server &s); + void execute(std::string buffer, ServerTCP &s); }; std::vector _hooks; void chat(); - void readData(const int sizeData); public: ServerTCP(const unsigned short int port, const unsigned short int sizeBuffer = 1024); + void registerHook(std::string command, hook handler); void bind(); void listen(); - void registerHook(std::string command, hook handler); + void disconnect(); + void stop(); }; } diff --git a/lesson_03/header/stock.hpp b/lesson_03/header/stock.hpp new file mode 100644 index 0000000..2faeef4 --- /dev/null +++ b/lesson_03/header/stock.hpp @@ -0,0 +1,31 @@ +/* + * stock.hpp + * + * Created on: 7 сент. 2022 г. + * Author: alexander + */ + +#pragma once + +#include +#include +#include +#include + +namespace zh +{ + +class Server // @suppress("Class has a virtual method and non-virtual destructor") +{ +protected: + std::unique_ptr _socket; + std::unique_ptr
_address; + std::unique_ptr _buffer; + const unsigned short int _port; +public: + Server(const unsigned short int port, const unsigned short int sizeBuffer); + virtual void bind() {} + virtual void listen() {} +}; + +} diff --git a/lesson_03/main.cpp b/lesson_03/main.cpp index cf64aad..370ad31 100644 --- a/lesson_03/main.cpp +++ b/lesson_03/main.cpp @@ -9,10 +9,44 @@ #include #include +#include + +void print(std::string buffer, zh::ServerTCP &s) +{ + std::cout << buffer << std::endl; +} + +void stop(std::string buffer, zh::ServerTCP &s) +{ + s.stop(); +} + +void disconnect(std::string buffer, zh::ServerTCP &s) +{ + s.disconnect(); +} + +void server(const int port) +{ + zh::ServerTCP tcpServer(port); + + tcpServer.registerHook("", print); + tcpServer.registerHook("disconnect", disconnect); + tcpServer.registerHook("stop", stop); + + tcpServer.bind(); + tcpServer.listen(); +} + +void client(const int port, const std::string &host) +{ + zh::ClientTCP tcpClient(host, port); + tcpClient.connect(); +} int main(int argc, char *argv[]) { - ap::Hub hub({{ "port", 'p', ap::REQUIRED }}); + ap::Hub hub({{ "port", 'p', ap::REQUIRED }, { "host", 'h', ap::REQUIRED }}); hub.readArguments(argc, argv); auto optionPort = hub.getOption('p'); @@ -21,12 +55,18 @@ int main(int argc, char *argv[]) std::cerr << "Порт не был установлен!" << std::endl; exit(EXIT_FAILURE); } + auto optionHost = hub.getOption('h'); + if (!optionHost.isSet()) + { + std::cerr << "Адрес не был установлен!" << std::endl; + exit(EXIT_FAILURE); + } int port = std::stoi(optionPort.getValues()[0]); + std::string host = optionHost.getValues()[0]; - zh::ServerTCP tcpServer(port); - tcpServer.bind(); - tcpServer.listen(); + server(port); +// client(port, host); return 0; } diff --git a/lesson_03/source/address.cpp b/lesson_03/source/address.cpp index 132fa77..48cf492 100644 --- a/lesson_03/source/address.cpp +++ b/lesson_03/source/address.cpp @@ -31,6 +31,18 @@ Address::Address(const unsigned short int family, const unsigned int addr, const _addr.sin_port = htons(port); } +Address::Address(const unsigned short int family, const std::string &addr, const unsigned short int port) +{ + memset(&_addr, 0, sizeof(_addr)); + _len = sizeof(_addr); + + _host = std::make_unique(gethostbyname(addr.c_str())); + + _addr.sin_family = family; + _addr.sin_addr.s_addr = *reinterpret_cast((*_host)->h_addr); + _addr.sin_port = htons(port); +} + unsigned int& Address::size() { return _len; diff --git a/lesson_03/source/buffer.cpp b/lesson_03/source/buffer.cpp new file mode 100644 index 0000000..05ebc35 --- /dev/null +++ b/lesson_03/source/buffer.cpp @@ -0,0 +1,40 @@ +/* + * buffer.cpp + * + * Created on: 7 сент. 2022 г. + * Author: alexander + */ + +#include +#include +#include + +namespace zh +{ + +Buffer::Buffer(const unsigned short int size) : _size(size) +{ + _buffer = std::make_unique(_size); +} + +const unsigned short int Buffer::getSize() const +{ + return _size; +} + +const std::string Buffer::getString() const +{ + return reinterpret_cast(_buffer.get()); +} + +void Buffer::clear() +{ + bzero(_buffer.get(), _size); +} + +Buffer::operator void*() +{ + return _buffer.get(); +} + +} diff --git a/lesson_03/source/client.cpp b/lesson_03/source/client.cpp new file mode 100644 index 0000000..4c7073e --- /dev/null +++ b/lesson_03/source/client.cpp @@ -0,0 +1,50 @@ +/* + * client.cpp + * + * Created on: 7 сент. 2022 г. + * Author: alexander + */ + +#include +#include +#include +#include + +namespace zh +{ + +ClientTCP::ClientTCP(const std::string &address, const unsigned short int port, const unsigned short int sizeBuffer) : Server(port, sizeBuffer), _connect(false), _connfd(-1) +{ + _socket = std::make_unique(AF_INET, SOCK_STREAM, IPPROTO_IP); + _address = std::make_unique
(AF_INET, address, port); +} + +void ClientTCP::connect() +{ + if (_connect) + { + std::cerr << "Клиентский сокет уже подключён к серверному сокету!" << std::endl; + return; + } + + if (::connect((*_socket), reinterpret_cast(&(*_address)), (*_address).size()) != 0) + std::cerr << "Не удаётся подключить клиентский сокет к серверному сокету!" << std::endl; + else + _connect = true; + + chat(); +} + +void ClientTCP::chat() +{ + while (_connect) + { + Buffer *bf = &(*_buffer); + bf->clear(); + std::cin.getline(reinterpret_cast(bf->operator void *()), bf->getSize()); + write(_connfd, *bf, bf->getSize()); + } + close(*_socket); +} + +} diff --git a/lesson_03/source/server.cpp b/lesson_03/source/server.cpp index 40fd8f8..9fd9ac3 100644 --- a/lesson_03/source/server.cpp +++ b/lesson_03/source/server.cpp @@ -9,20 +9,16 @@ #include #include #include +#include namespace zh { -Server::Server(const unsigned short int port) : _port(port), _connfd(-1) -{ - _sizeClient = sizeof(*_client); -} - ServerTCP::Hook::Hook(std::string command, hook handler) : _command(command), _handler(handler) { } -void ServerTCP::Hook::execute(std::string buffer, Server &s) +void ServerTCP::Hook::execute(std::string buffer, ServerTCP &s) { if (_command == "") { @@ -43,11 +39,11 @@ void ServerTCP::registerHook(std::string command, hook handler) _hooks.push_back({ command, handler }); } -ServerTCP::ServerTCP(const unsigned short int port, const unsigned short int sizeBuffer) : Server(port), _bind(false), _sizeBuffer(sizeBuffer) +ServerTCP::ServerTCP(const unsigned short int port, const unsigned short int sizeBuffer) : Server(port, sizeBuffer), _bind(false), _connfd(-1), _listenLoop(true) { _socket = std::make_unique(AF_INET, SOCK_STREAM, IPPROTO_IP); - _local = std::make_unique
(AF_INET, INADDR_ANY, port); - _buffer = std::make_unique(sizeBuffer); + _address = std::make_unique
(AF_INET, INADDR_ANY, port); + _sizeClient = sizeof(_client); } void ServerTCP::bind() @@ -58,7 +54,7 @@ void ServerTCP::bind() return; } - if (::bind((*_socket), reinterpret_cast(&(*_local)), (*_local).size()) != 0) + if (::bind((*_socket), reinterpret_cast(&(*_address)), (*_address).size()) != 0) std::cerr << "Не удаётся связать адрес с дескриптором слушающего сокета!" << std::endl; else _bind = true; @@ -79,27 +75,41 @@ void ServerTCP::listen() std::cerr << "Не удаётся верифицировать и принять пакеты от клиента!" << std::endl; return; } + else + _listenLoop = true; // Обработка соединения с клиентом chat(); } } -void ServerTCP::readData(const int sizeData) -{ - -} - void ServerTCP::chat() { - while (true) + while (_listenLoop) { - bzero(_buffer.get(), _sizeBuffer); - read(_connfd, _buffer.get(), 4); - std::cout << *reinterpret_cast(_buffer.get()) << std::endl; - close(_connfd); - break; + Buffer *bf = &(*_buffer); + bf->clear(); + int size = read(_connfd, *bf, bf->getSize()); + if (size > 0) + std::for_each(_hooks.begin(), _hooks.end(), [&](Hook &hook) + { + hook.execute(bf->getString(), *this); + }); + else if (size < 0) + break; } + close(_connfd); +} + +void ServerTCP::stop() +{ + _listenLoop = false; + _bind = 0; +} + +void ServerTCP::disconnect() +{ + _listenLoop = false; } } diff --git a/lesson_03/source/stock.cpp b/lesson_03/source/stock.cpp new file mode 100644 index 0000000..3e8ca0a --- /dev/null +++ b/lesson_03/source/stock.cpp @@ -0,0 +1,18 @@ +/* + * stock.cpp + * + * Created on: 7 сент. 2022 г. + * Author: alexander + */ + +#include + +namespace zh +{ + +Server::Server(const unsigned short int port, const unsigned short int sizeBuffer) : _port(port) +{ + _buffer = std::make_unique(sizeBuffer); +} + +} -- 2.40.1 From 4a5943ce9f7b4738558e9d22d0a8ebac3b9ee46f Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Wed, 7 Sep 2022 16:43:05 +0300 Subject: [PATCH 4/5] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D1=8B=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BF=D1=83=D1=81=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B8=D0=BB?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lesson_03/main.cpp | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/lesson_03/main.cpp b/lesson_03/main.cpp index 370ad31..04d2d5b 100644 --- a/lesson_03/main.cpp +++ b/lesson_03/main.cpp @@ -46,7 +46,12 @@ void client(const int port, const std::string &host) int main(int argc, char *argv[]) { - ap::Hub hub({{ "port", 'p', ap::REQUIRED }, { "host", 'h', ap::REQUIRED }}); + ap::Hub hub({ + { "port", 'p', ap::REQUIRED }, + { "host", 'h', ap::OPTIONAL }, + { "server", 's', ap::NO }, + { "client", 'c', ap::NO } + }); hub.readArguments(argc, argv); auto optionPort = hub.getOption('p'); @@ -55,18 +60,36 @@ int main(int argc, char *argv[]) std::cerr << "Порт не был установлен!" << std::endl; exit(EXIT_FAILURE); } - auto optionHost = hub.getOption('h'); - if (!optionHost.isSet()) + + int port = std::stoi(optionPort.getValues()[0]); + + auto optionClient = hub.getOption('c'); + auto optionServer = hub.getOption('s'); + + if (optionClient.isSet()) { - std::cerr << "Адрес не был установлен!" << std::endl; + auto optionHost = hub.getOption('h'); + if (!optionHost.isSet()) + { + std::cerr << "Адрес не был установлен!" << std::endl; + exit(EXIT_FAILURE); + } + + std::string host = optionHost.getValues()[0]; + + client(port, host); + } + else if (optionServer.isSet()) + server(port); + else + { + std::cerr << "Необходимо установить режим запуска:" << std::endl + << "\t-c\t--client\tЗапуск в режиме клиента" << std::endl + << "\t-s\t--server\tЗапуск в режиме сервера" << std::endl + << "\t-h\t--host\t\tУказать IP-адрес сервера" << std::endl + << "\t-p\t--port\t\tУказать порт" << std::endl; exit(EXIT_FAILURE); } - int port = std::stoi(optionPort.getValues()[0]); - std::string host = optionHost.getValues()[0]; - - server(port); -// client(port, host); - return 0; } -- 2.40.1 From 09446a63f7502cf4a9f1ad43a1e2bd9d6526408c Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Wed, 7 Sep 2022 19:09:17 +0300 Subject: [PATCH 5/5] =?UTF-8?q?fix=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BA=D0=B8/=D1=87=D1=82=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lesson_03/header/buffer.hpp | 2 +- lesson_03/header/client.hpp | 1 - lesson_03/main.cpp | 2 +- lesson_03/source/buffer.cpp | 4 ++-- lesson_03/source/client.cpp | 18 +++++++++++++----- lesson_03/source/server.cpp | 13 +++++++++---- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lesson_03/header/buffer.hpp b/lesson_03/header/buffer.hpp index 208bd7b..1705611 100644 --- a/lesson_03/header/buffer.hpp +++ b/lesson_03/header/buffer.hpp @@ -22,7 +22,7 @@ public: const unsigned short int getSize() const; const std::string getString() const; void clear(); - operator void*(); + operator char*(); }; } diff --git a/lesson_03/header/client.hpp b/lesson_03/header/client.hpp index 08ec0a0..d5e83f0 100644 --- a/lesson_03/header/client.hpp +++ b/lesson_03/header/client.hpp @@ -16,7 +16,6 @@ class ClientTCP: public Server // @suppress("Class has a virtual method and non- { private: bool _connect; - int _connfd; void chat(); public: diff --git a/lesson_03/main.cpp b/lesson_03/main.cpp index 04d2d5b..bb9600d 100644 --- a/lesson_03/main.cpp +++ b/lesson_03/main.cpp @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - std::string host = optionHost.getValues()[0]; + auto host = optionHost.getValues()[0]; client(port, host); } diff --git a/lesson_03/source/buffer.cpp b/lesson_03/source/buffer.cpp index 05ebc35..706ab6a 100644 --- a/lesson_03/source/buffer.cpp +++ b/lesson_03/source/buffer.cpp @@ -32,9 +32,9 @@ void Buffer::clear() bzero(_buffer.get(), _size); } -Buffer::operator void*() +Buffer::operator char*() { - return _buffer.get(); + return reinterpret_cast(_buffer.get()); } } diff --git a/lesson_03/source/client.cpp b/lesson_03/source/client.cpp index 4c7073e..a70bd52 100644 --- a/lesson_03/source/client.cpp +++ b/lesson_03/source/client.cpp @@ -13,7 +13,7 @@ namespace zh { -ClientTCP::ClientTCP(const std::string &address, const unsigned short int port, const unsigned short int sizeBuffer) : Server(port, sizeBuffer), _connect(false), _connfd(-1) +ClientTCP::ClientTCP(const std::string &address, const unsigned short int port, const unsigned short int sizeBuffer) : Server(port, sizeBuffer), _connect(false) { _socket = std::make_unique(AF_INET, SOCK_STREAM, IPPROTO_IP); _address = std::make_unique
(AF_INET, address, port); @@ -27,7 +27,7 @@ void ClientTCP::connect() return; } - if (::connect((*_socket), reinterpret_cast(&(*_address)), (*_address).size()) != 0) + if (::connect(*_socket, reinterpret_cast(&(*_address)), (*_address).size()) != 0) std::cerr << "Не удаётся подключить клиентский сокет к серверному сокету!" << std::endl; else _connect = true; @@ -37,12 +37,20 @@ void ClientTCP::connect() void ClientTCP::chat() { + Buffer *bf = &(*_buffer); while (_connect) { - Buffer *bf = &(*_buffer); bf->clear(); - std::cin.getline(reinterpret_cast(bf->operator void *()), bf->getSize()); - write(_connfd, *bf, bf->getSize()); + std::cin.getline(*bf, bf->getSize()); + write(*_socket, *bf, bf->getSize()); + bf->clear(); + if (read(*_socket, *bf, bf->getSize()) > 0) + { + if (bf->getString() == "exit") + break; + else + std::cout << '\t' << bf->getString() << std::endl; + } } close(*_socket); } diff --git a/lesson_03/source/server.cpp b/lesson_03/source/server.cpp index 9fd9ac3..56ee3bc 100644 --- a/lesson_03/source/server.cpp +++ b/lesson_03/source/server.cpp @@ -26,8 +26,7 @@ void ServerTCP::Hook::execute(std::string buffer, ServerTCP &s) } else { - auto pos = buffer.find_first_of(_command); - if (pos != std::string::npos && pos == 0) + if (buffer == _command) { _handler(buffer, s); } @@ -54,7 +53,7 @@ void ServerTCP::bind() return; } - if (::bind((*_socket), reinterpret_cast(&(*_address)), (*_address).size()) != 0) + if (::bind(*_socket, reinterpret_cast(&(*_address)), (*_address).size()) != 0) std::cerr << "Не удаётся связать адрес с дескриптором слушающего сокета!" << std::endl; else _bind = true; @@ -85,16 +84,22 @@ void ServerTCP::listen() void ServerTCP::chat() { + Buffer *bf = &(*_buffer); while (_listenLoop) { - Buffer *bf = &(*_buffer); bf->clear(); int size = read(_connfd, *bf, bf->getSize()); if (size > 0) + { std::for_each(_hooks.begin(), _hooks.end(), [&](Hook &hook) { hook.execute(bf->getString(), *this); }); + if (!_listenLoop) + write(_connfd, "exit", 4); + else + write(_connfd, "OK", 2); + } else if (size < 0) break; } -- 2.40.1