From a8c2f5e87f79efa2653770a3ebd976abb0beaea2 Mon Sep 17 00:00:00 2001 From: k-morozov Date: Tue, 4 Aug 2020 11:46:35 +0300 Subject: [PATCH] - add ObjectPool for connections - rewrite find free connections - add doc - add check is open socket --- src/client/CMakeLists.txt | 2 +- src/client/client/client.cpp | 42 +++++++++-------- src/client/client/client.h | 4 +- src/client/control/control.cpp | 2 +- src/client/gui/mainwindow.cpp | 4 ++ src/server/CMakeLists.txt | 3 +- src/server/channel/channel.cpp | 1 + src/server/channel/channels_manager.cpp | 5 ++- src/server/connection/connection.cpp | 38 ++++++++++------ src/server/connection/connection.h | 44 +++++++++++++++++- src/server/connection/connection_manager.cpp | 43 ++++++++++++++++++ src/server/connection/connection_manager.h | 47 ++++++++++++++++++++ src/server/connection/isubscriber.h | 3 ++ src/server/server.h | 13 ++---- 14 files changed, 204 insertions(+), 47 deletions(-) create mode 100644 src/server/connection/connection_manager.cpp create mode 100644 src/server/connection/connection_manager.h diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 51a994b..7592e1c 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -37,7 +37,7 @@ add_executable(${CLIENT_BIN} ${CLIENT_SOURCES}) target_include_directories(${CLIENT_BIN} PUBLIC .) #**************************************************************************************************** -find_package(Boost COMPONENTS system date_time program_options regex REQUIRED) +find_package(Boost COMPONENTS system date_time REQUIRED) set_target_properties(${CLIENT_BIN} PROPERTIES CXX_STANDARD 17 diff --git a/src/client/client/client.cpp b/src/client/client/client.cpp index 102620f..83452c5 100644 --- a/src/client/client/client.cpp +++ b/src/client/client/client.cpp @@ -1,5 +1,4 @@ #include -//#include void Client::write(const std::string& message) { text_request_ptr text_request = std::make_shared(login, room_id, message); @@ -60,7 +59,9 @@ void Client::send_login_packet(packet_ptr packet) { packet->get_length_data()), error_code); if (error_code) { - sock.close(); + if (sock.is_open()) { + sock.close(); + } std::cout << "error when send login" << std::endl; return ; } @@ -69,7 +70,9 @@ void Client::send_login_packet(packet_ptr packet) { boost::asio::read(sock, boost::asio::buffer(response->get_header(), Block::Header), error_code); if (error_code) { - sock.close(); + if (sock.is_open()) { + sock.close(); + } std::cout << "error when read login-id" << std::endl; return ; } @@ -89,19 +92,16 @@ void Client::send_login_packet(packet_ptr packet) { } else { -// good_client_is_registred(); emit send_input_code(InputCode::RegistrOK); } else { if (response->get_loginid()==-1) { -// emit bad_client_is_autorisation(); emit send_input_code(InputCode::IncorrectAutor); this->close(); return; } else { -// good_client_is_autorisation(); emit send_input_code(InputCode::AutorOK); } } @@ -154,7 +154,9 @@ void Client::read_response_header() { } } else { - sock.close(); + if (sock.is_open()) { + sock.close(); + } } }); } @@ -165,12 +167,12 @@ void Client::read_response_data(registr_response_ptr packet) { boost::asio::async_read(sock, boost::asio::buffer(packet->get_data(), packet->get_length_data()), [this, packet](boost::system::error_code error, std::size_t) { if (!error) { -// std::cout << "read_response_data" << std::endl; - read_response_header(); } else { - sock.close(); + if (sock.is_open()) { + sock.close(); + } } }); } @@ -181,11 +183,12 @@ void Client::read_response_data(autor_response_ptr packet) { boost::asio::async_read(sock, boost::asio::buffer(packet->get_data(), packet->get_length_data()), [this, packet](boost::system::error_code error, std::size_t) { if (!error) { -// std::cout << "read_response_data" << std::endl; read_response_header(); } else { - sock.close(); + if (sock.is_open()) { + sock.close(); + } } }); } @@ -204,14 +207,13 @@ void Client::read_response_data(text_response_ptr packet) { read_response_header(); } else { - sock.close(); + if (sock.is_open()) { + sock.close(); + } } }); } -//void Client::read_response_join_room(join_room_request_ptr) { - -//} void Client::send_request_header() { boost::asio::async_write(sock, boost::asio::buffer(packets_to_server.front()->get_header(), Block::Header), [this](boost::system::error_code ec, std::size_t) { @@ -220,7 +222,9 @@ void Client::send_request_header() { } else { std::cout << "error start_sending" << std::endl; - sock.close(); + if (sock.is_open()) { + sock.close(); + } } }); } @@ -234,7 +238,9 @@ void Client::send_request_data() { if (!packets_to_server.empty()) send_request_header(); } else { - sock.close(); + if (sock.is_open()) { + sock.close(); + } } }); } diff --git a/src/client/client/client.h b/src/client/client/client.h index c08e77c..cb10022 100644 --- a/src/client/client/client.h +++ b/src/client/client/client.h @@ -53,7 +53,9 @@ class Client: public QObject { */ void close() { boost::asio::post(io_service, [this]() { - sock.close(); + if (sock.is_open()) { + sock.close(); + } }); } diff --git a/src/client/control/control.cpp b/src/client/control/control.cpp index 90e156c..f1bd063 100644 --- a/src/client/control/control.cpp +++ b/src/client/control/control.cpp @@ -21,7 +21,7 @@ Control::Control() { void Control::connect_to_server(const std::string& login, const std::string& password, TypeCommand command) { boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); - auto endpoints = resolver.resolve("127.0.0.1", "7777"); + auto endpoints = resolver.resolve("172.17.0.1", "7777"); input_request_ptr request; if (command==TypeCommand::RegistrationRequest) { diff --git a/src/client/gui/mainwindow.cpp b/src/client/gui/mainwindow.cpp index 40f0527..e66b079 100644 --- a/src/client/gui/mainwindow.cpp +++ b/src/client/gui/mainwindow.cpp @@ -33,6 +33,8 @@ void MainWindow::on_push_autorisation_clicked() password = ui->password->text(); if (logon.isEmpty() || password.isEmpty()) return; send_autorisation_info(logon.toStdString(), password.toStdString()); + ui->logon->clear(); + ui->password->clear(); } void MainWindow::on_push_send_clicked() @@ -68,6 +70,8 @@ void MainWindow::on_push_registration_clicked() password = ui->password->text(); if (logon.isEmpty() || password.isEmpty()) return; send_registration_info(logon.toStdString(), password.toStdString()); + ui->logon->clear(); + ui->password->clear(); } void MainWindow::on_push_change_room_id_clicked() diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 927d717..5ffef7e 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -26,6 +26,7 @@ set(CHANNELS_SRC set(CONNECTIONS_SRC ${DIR_CONNECTION}/isubscriber.h ${DIR_CONNECTION}/isubscriber.cpp ${DIR_CONNECTION}/connection.h ${DIR_CONNECTION}/connection.cpp + ${DIR_CONNECTION}/connection_manager.h ${DIR_CONNECTION}/connection_manager.cpp ) #**************************************************************************************************** @@ -38,7 +39,7 @@ set(SERVER_SOURCES add_executable(${SERVER_BIN} ${SERVER_SOURCES}) target_include_directories(${SERVER_BIN} PUBLIC .) #**************************************************************************************************** -find_package(Boost COMPONENTS system date_time program_options regex REQUIRED) +find_package(Boost COMPONENTS system date_time REQUIRED) set_target_properties(${SERVER_BIN} PROPERTIES CXX_STANDARD 17 diff --git a/src/server/channel/channel.cpp b/src/server/channel/channel.cpp index ceb2247..da23778 100644 --- a/src/server/channel/channel.cpp +++ b/src/server/channel/channel.cpp @@ -16,6 +16,7 @@ void Channel::join(subscriber_ptr new_subsciber) { } void Channel::leave(subscriber_ptr subsciber) { + subsciber->set_busy(false); mutex_subs.lock(); subscribers.erase(subsciber->get_client_id()); mutex_subs.unlock(); diff --git a/src/server/channel/channels_manager.cpp b/src/server/channel/channels_manager.cpp index 00728aa..32d1c8d 100644 --- a/src/server/channel/channels_manager.cpp +++ b/src/server/channel/channels_manager.cpp @@ -2,6 +2,7 @@ ChannelsManager::ChannelsManager() { + LOG4CPLUS_INFO(logger, "create ChannelsManager"); } void ChannelsManager::join(subscriber_ptr new_sub, identifier_t room_id, database_ptr db) { @@ -28,7 +29,7 @@ void ChannelsManager::join(subscriber_ptr new_sub, identifier_t room_id, databas else { LOG4CPLUS_INFO(logger, "New subsciber client_id="<< it2->first - << "in room_id=" << it2->second); + << " in room_id=" << it2->second); } } @@ -60,5 +61,7 @@ void ChannelsManager::leave(subscriber_ptr sub) { else { LOG4CPLUS_ERROR(logger, "no room room_id=" << room_id); } + + sub->set_busy(false); } diff --git a/src/server/connection/connection.cpp b/src/server/connection/connection.cpp index c032262..c615cd3 100644 --- a/src/server/connection/connection.cpp +++ b/src/server/connection/connection.cpp @@ -19,36 +19,38 @@ void Connection::read_request_header() { switch (request->get_type_data()) { case TypeCommand::Unknown: - LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << "--> "); + LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << ": "); break; case TypeCommand::RegistrationRequest: - LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << "--> "); + LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << ": "); read_request_body(std::make_shared(request)); break; case TypeCommand::RegistrationResponse: case TypeCommand::AuthorisationRequest: - LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << "--> "); + LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << ": "); read_request_body(std::make_shared(request)); break; case TypeCommand::AutorisationResponse: case TypeCommand::EchoRequest: - LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << "--> "); + LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << ": "); read_request_body(std::make_shared(request)); break; case TypeCommand::EchoResponse: case TypeCommand::JoinRoomRequest: - LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << "--> "); + LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << ": "); read_request_body(std::make_shared(request)); break; case TypeCommand::JoinRoomResponse: case TypeCommand::LeaveRoomRequest: default: - LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << "--> "); + LOG4CPLUS_INFO(logger, get_command_str(request->get_type_data()) << ": "); break; } } else { ChannelsManager::Instance().leave(shared_from_this()); - socket.close(); + if (socket.is_open()) { + socket.close(); + } } }); @@ -73,6 +75,7 @@ void Connection::read_request_body(registr_request_ptr request) { else { LOG4CPLUS_WARN(logger, "this client was add to db early"); client_id=-1; + busy = false; } input_res_ptr response = std::make_shared(client_id); @@ -89,7 +92,9 @@ void Connection::read_request_body(registr_request_ptr request) { } else { ChannelsManager::Instance().leave(shared_from_this()); - socket.close(); + if (socket.is_open()) { + socket.close(); + } } }); } @@ -105,7 +110,6 @@ void Connection::read_request_body(autor_request_ptr request) { LOG4CPLUS_INFO(logger, "login=" << request->get_login() << ", pwd=" << request->get_password()); client_id = db->check_client(login, password); - input_res_ptr response = std::make_shared(client_id); LOG4CPLUS_INFO(logger, "AutorisationResponse: vers=" << response->get_protocol_version() << ", command=" @@ -114,15 +118,19 @@ void Connection::read_request_body(autor_request_ptr request) { if (client_id!=-1) { db->add_logins(login, response->get_loginid(), password); + } else { + busy = false; } boost::asio::write(socket, boost::asio::buffer(response->get_header(), Block::Header)); boost::asio::write(socket, boost::asio::buffer(response->get_data(), response->get_length_data())); - read_request_header(); + if (client_id!=-1) read_request_header(); } else { ChannelsManager::Instance().leave(shared_from_this()); - socket.close(); + if (socket.is_open()) { + socket.close(); + } } }); } @@ -145,7 +153,9 @@ void Connection::read_request_body(text_request_ptr request) { } else { ChannelsManager::Instance().leave(shared_from_this()); - socket.close(); + if (socket.is_open()) { + socket.close(); + } } }); @@ -167,7 +177,9 @@ void Connection::read_request_body(join_room_request_ptr request) { } else { ChannelsManager::Instance().leave(shared_from_this()); - socket.close(); + if (socket.is_open()) { + socket.close(); + } } }); diff --git a/src/server/connection/connection.h b/src/server/connection/connection.h index 52521f5..ef3d61f 100644 --- a/src/server/connection/connection.h +++ b/src/server/connection/connection.h @@ -26,7 +26,10 @@ class Connection : public ISubscriber, public std::enable_shared_from_this packets_to_client; @@ -77,8 +116,9 @@ class Connection : public ISubscriber, public std::enable_shared_from_thisis_busy(); + }); + if (it!=pool_connections.end()) { + (*it)->set_busy(); + (*it)->init(std::move(_socket)); + + LOG4CPLUS_INFO(logger, + "use old connection, current size pool = " << pool_connections.size()); + print_pool(); + return (*it); + } + else { + auto block = std::make_shared(std::move(_socket), db); + pool_connections.push_back(block); + + LOG4CPLUS_INFO(logger, + "create new connection, current size pool = " << pool_connections.size()); + print_pool(); + return block; + } + +} + +void ConnectionManager::print_pool() const noexcept { + LOG4CPLUS_INFO(logger, "[connections]"); + for(const auto& obj:pool_connections) { + if (obj->get_client_id()>0) { + LOG4CPLUS_INFO(logger, + "obj: login=" << obj->get_login() << ", id=" << obj->get_client_id() << ", status: " << + (obj->is_busy() ? "busy" : "free")); + } else { + LOG4CPLUS_INFO(logger, + "obj: current connection not init"); + } + } +} + diff --git a/src/server/connection/connection_manager.h b/src/server/connection/connection_manager.h new file mode 100644 index 0000000..e44076e --- /dev/null +++ b/src/server/connection/connection_manager.h @@ -0,0 +1,47 @@ +#ifndef CONNECTIONMANAGER_H +#define CONNECTIONMANAGER_H + +#include "connection.h" + + +/** + * @brief ConnectionManager + * + * @details Manager to control connections from clinets. Use ObjectPool. + */ +class ConnectionManager +{ +public: + ConnectionManager(): + logger(LOGGER("ConnectionManager")), + db(std::make_shared("history.db")) + { + LOG4CPLUS_INFO(logger, + "create ConnectionManager"); + } + ConnectionManager(const ConnectionManager&) = delete; + + /** + * @brief get new or old connection for new client + * @param _socket + */ + connection_ptr get_connection(boost::asio::ip::tcp::socket&& _socket); + + ~ConnectionManager() { + for (auto& value_con: pool_connections) { + value_con->set_busy(false); + } + pool_connections.clear(); + } +private: + std::vector pool_connections; + log4cplus::Logger logger; + database_ptr db; + + /** + * @brief print all connections + * */ + void print_pool() const noexcept; +}; + +#endif // CONNECTIONMANAGER_H diff --git a/src/server/connection/isubscriber.h b/src/server/connection/isubscriber.h index b86d3b3..38d1aa5 100644 --- a/src/server/connection/isubscriber.h +++ b/src/server/connection/isubscriber.h @@ -43,6 +43,9 @@ class ISubscriber */ virtual const std::string& get_login() const = 0; + virtual bool is_busy() const noexcept = 0; + virtual void set_busy(bool flag = true) noexcept = 0; + virtual ~ISubscriber() = default; }; diff --git a/src/server/server.h b/src/server/server.h index 75a21ea..7771061 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -4,7 +4,7 @@ #include #include -#include +#include using boost::asio::ip::tcp; @@ -20,8 +20,7 @@ class Server { */ Server(): endpoint(boost::asio::ip::tcp::v4(), 7777), - acceptor(io_service, endpoint), - db(std::make_shared("history.db")) + acceptor(io_service, endpoint) { scan_acception(); } @@ -37,10 +36,8 @@ class Server { boost::asio::io_service io_service; boost::asio::ip::tcp::endpoint endpoint; boost::asio::ip::tcp::acceptor acceptor; - database_ptr db; - - std::vector server_connections; + ConnectionManager connect_manager; private: /** * @brief Handle new connected clint. @@ -51,9 +48,7 @@ class Server { void scan_acception() { acceptor.async_accept([this](const boost::system::error_code& error, tcp::socket sock) { if (!error) { - auto connect_ptr = std::make_shared(std::move(sock), db); - server_connections.push_back(connect_ptr); - connect_ptr->start(); + connect_manager.get_connection(std::move(sock))->start(); } scan_acception();