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); +} + +}