From b52139cb256063792a2ffbb7e58c33bd309f416d Mon Sep 17 00:00:00 2001 From: zcy <290198252@qq.com> Date: Wed, 9 Mar 2022 00:28:31 +0800 Subject: [PATCH] no message --- examples/proto_debuger/msgdef.h | 5 + examples/proto_debuger/new_monitor_form.cpp | 20 +- examples/proto_debuger/proto_debuger.vcxproj | 10 +- .../proto_debuger.vcxproj.filters | 9 +- examples/proto_debuger/websocket_client.cpp | 285 +++++++++++++++--- examples/proto_debuger/websocket_client.h | 78 ++++- .../proto_debuger/websocket_client_form.cpp | 2 + .../proto_debuger/websocket_client_form.h | 4 - examples/proto_debuger/websocket_server.cpp | 97 ++++++ examples/proto_debuger/websocket_server.h | 46 +++ 10 files changed, 491 insertions(+), 65 deletions(-) create mode 100644 examples/proto_debuger/websocket_server.cpp create mode 100644 examples/proto_debuger/websocket_server.h diff --git a/examples/proto_debuger/msgdef.h b/examples/proto_debuger/msgdef.h index 30b721ae..800b7f3f 100644 --- a/examples/proto_debuger/msgdef.h +++ b/examples/proto_debuger/msgdef.h @@ -13,3 +13,8 @@ #define WM_USER_TCP_CLIENT_CLOSE (WM_USER + 11) #define WM_USER_TCP_SERVER_CLOSE (WM_USER + 12) #define WM_USER_UDP_GROUP_CLOSE (WM_USER + 13) + +#define WM_ADD_WEBSOCKET_SERVER (WM_USER + 14) +#define WM_ADD_WEBSOCKET_SERVER_CLOSE (WM_USER + 15) +#define WM_ADD_WEBSOCKET_CLIENT (WM_USER + 16) +#define WM_ADD_WEBSOCKET_CLIENT_CLOSE (WM_USER + 17) diff --git a/examples/proto_debuger/new_monitor_form.cpp b/examples/proto_debuger/new_monitor_form.cpp index 76ee4b49..d7536983 100644 --- a/examples/proto_debuger/new_monitor_form.cpp +++ b/examples/proto_debuger/new_monitor_form.cpp @@ -10,6 +10,7 @@ #include "base_form.h" #include "tcp_client.h" #include "udp_libevent.h" +#include "websocket_client.h" #include "utils.h" #include @@ -106,7 +107,6 @@ void NewMonitorForm::InitWindow() ui::Button* btn_add_new = dynamic_cast(FindControl(L"open_button")); if (nullptr != btn_add_new) { btn_add_new->AttachClick([this](ui::EventArgs*) { - if(m_combo_type->GetText() == L"uart"){ UINT PortNum = 0; for (int i = 3; m_uart_select_combo->GetText()[i] != '\0'; i++) //转换为数字 @@ -189,7 +189,6 @@ void NewMonitorForm::InitWindow() printf("postmessage error :%d\r\n", GetLastError()); } } - if (m_combo_type->GetText() == L"udp group") { wprintf(L"%s\r\n", m_ip_select->GetText().c_str()); wprintf(L"%s\r\n", m_port_select->GetText().c_str()); @@ -208,7 +207,24 @@ void NewMonitorForm::InitWindow() printf("postmessage error :%d\r\n", GetLastError()); } } + if (m_combo_type->GetText() == L"websocket client") { + wprintf(L"%s\r\n", m_ip_select->GetText().c_str()); + wprintf(L"%s\r\n", m_port_select->GetText().c_str()); + int port = atoi(wstring2string(m_port_select->GetText()).c_str()); + UdpDataGramLibevent* udp = new UdpDataGramLibevent("0.0.0.0", + port, wstring2string(m_ip_select->GetText().c_str())); + TcpServerInfo* p = new TcpServerInfo; + p->ip = m_ip_select->GetText(); + p->port = port; + p->socket_fd = udp->SocketFD(); + printf("开启服务端 %d \r\n", p->socket_fd); + auto succ = ::PostMessage(m_parent->GetHWND(), + WM_ADD_WEBSOCKET_SERVER, (WPARAM)p, (LPARAM)udp); + if (!succ) { + printf("postmessage error :%d\r\n", GetLastError()); + } + } return true; }); } diff --git a/examples/proto_debuger/proto_debuger.vcxproj b/examples/proto_debuger/proto_debuger.vcxproj index 68f51845..717f62cc 100644 --- a/examples/proto_debuger/proto_debuger.vcxproj +++ b/examples/proto_debuger/proto_debuger.vcxproj @@ -81,9 +81,9 @@ true - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\;$(ProjectDir)third\include\libevent\include;$(ProjectDir);$(ProjectDir)third\include\lua;$(ProjectDir)third\include\;D:\include + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\;$(ProjectDir)third\include\libevent\include;$(ProjectDir);$(ProjectDir)third\include\lua;$(ProjectDir)third\include\;D:\include;I:\home\.conan\data\OPENSSL\1.1.1\_\_\build\149ed843ea788702da310f9d8f34c34c2a72994a\pkgsrc\inc32 $(ReferencePath) - $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(ProjectDir)third\lib + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(ProjectDir)third\lib;I:\home\.conan\data\OPENSSL\1.1.1\_\_\build\149ed843ea788702da310f9d8f34c34c2a72994a\pkgsrc\out32dll false @@ -127,11 +127,12 @@ _WEBSOCKETPP_CPP11_TYPE_TRAITS_;_WEBSOCKETPP_CPP11_RANDOM_DEVICE_;ASIO_STANDALONE ;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;_WSPIAPI_H_;_WINSOCKAPI_;%(PreprocessorDefinitions) true MultiThreadedDebug + /bigobj %(AdditionalOptions) Windows true - ws2_32.lib;event_extra.lib;event_core.lib;event.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;lua53.lib;%(AdditionalDependencies) + ws2_32.lib;event_extra.lib;event_core.lib;event.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;lua53.lib;Bcrypt.lib;ssleay32.lib;libeay32.lib;%(AdditionalDependencies) @@ -181,8 +182,10 @@ + + @@ -200,7 +203,6 @@ - diff --git a/examples/proto_debuger/proto_debuger.vcxproj.filters b/examples/proto_debuger/proto_debuger.vcxproj.filters index b9c7244a..2bdcd261 100644 --- a/examples/proto_debuger/proto_debuger.vcxproj.filters +++ b/examples/proto_debuger/proto_debuger.vcxproj.filters @@ -66,10 +66,13 @@ 婧愭枃浠 + + 婧愭枃浠 + 婧愭枃浠 - + 婧愭枃浠 @@ -125,10 +128,10 @@ 澶存枃浠 - + 澶存枃浠 - + 澶存枃浠 diff --git a/examples/proto_debuger/websocket_client.cpp b/examples/proto_debuger/websocket_client.cpp index 27977c2a..b16838fc 100644 --- a/examples/proto_debuger/websocket_client.cpp +++ b/examples/proto_debuger/websocket_client.cpp @@ -1,70 +1,255 @@ - -#include -#include - -#include - -typedef websocketpp::client client; - -using websocketpp::lib::placeholders::_1; -using websocketpp::lib::placeholders::_2; -using websocketpp::lib::bind; - -// pull out the type of messages sent by our config -typedef websocketpp::config::asio_client::message_type::ptr message_ptr; +#include "websocket_client.h" // This message handler will be invoked once for each incoming message. It // prints the message and then sends a copy of the message back to the server. -void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) { +void on_message(WebsocketClient* c, websocketpp::connection_hdl hdl, message_ptr msg) { std::cout << "on_message called with hdl: " << hdl.lock().get() << " and message: " << msg->get_payload() << std::endl; websocketpp::lib::error_code ec; - - c->send(hdl, msg->get_payload(), msg->get_opcode(), ec); + // c->send(hdl, msg->get_payload(), msg->get_opcode(), ec); if (ec) { std::cout << "Echo failed because: " << ec.message() << std::endl; } + if (c->m_onread != nullptr) { + c->m_onread(c,msg->get_payload()); + } } -int main11(int argc, char* argv[]) { - // Create a client endpoint - client c; - std::string uri = "ws://localhost:9002"; +int WebsocketClient::SendMsg(const char * str,uint32_t len, + websocketpp::frame::opcode::value opcode) +{ + if(this->m_status != WebsocketClient::CONNECTED) + return -1; + if(m_tls){ + websocketpp::lib::error_code ec; + this->m_client_tls.send(m_conn_tls,str,len,opcode,ec); + if (ec) { + std::cout << "Echo failed because: " << ec.message() << std::endl; + return -1; + } + }else{ + websocketpp::lib::error_code ec; + this->m_client.send(m_conn,str,len,opcode,ec); + if (ec) { + std::cout << "Echo failed because: " << ec.message() << std::endl; + return -1; + } + } + return 0; +} - if (argc == 2) { - uri = argv[1]; - } + +void on_open(WebsocketClient * c, websocketpp::connection_hdl hdl) { + if(c->m_tls){ + TlsClient::connection_ptr con = c->m_client_tls.get_con_from_hdl(hdl); + uint32_t usocket = con->get_raw_socket().native_handle(); + auto m_server = con->get_response_header("Server"); + std::cout<<"open from server"<m_status = WebsocketClient::CONNECTED; + if (c->m_on_connected != nullptr) { + c->m_on_connected(c); + } + }else{ + Client::connection_ptr con = c->m_client.get_con_from_hdl(hdl); + uint32_t usocket = con->get_raw_socket().native_handle(); + auto m_server = con->get_response_header("Server"); + std::cout<<"open from server"<m_status = WebsocketClient::CONNECTED; + if (c->m_on_connected != nullptr) { + c->m_on_connected(c); + } + } +} - try { - // Set logging to be pretty verbose (everything except message payloads) - c.set_access_channels(websocketpp::log::alevel::all); - c.clear_access_channels(websocketpp::log::alevel::frame_payload); - // Initialize ASIO - c.init_asio(); + +void on_close(WebsocketClient * c, websocketpp::connection_hdl hdl) { + // m_status = "Open"; - // Register our message handler - c.set_message_handler(bind(&on_message, &c, ::_1, ::_2)); + // client::connection_ptr con = c->get_con_from_hdl(hdl); + // m_server = con->get_response_header("Server"); + c->m_status = WebsocketClient::CLOSED; + std::cout<<"on_close"<m_on_disconnected != nullptr) { + c->m_on_disconnected(c,WebsocketClient::CloseReason::LOCAL_CLOSED); + } +} - websocketpp::lib::error_code ec; - client::connection_ptr con = c.get_connection(uri, ec); - if (ec) { - std::cout << "could not create connection because: " << ec.message() << std::endl; - return 0; - } +void on_fail(WebsocketClient * c, websocketpp::connection_hdl hdl) { + std::cout<<"on_fail"<m_client.get_con_from_hdl(hdl); + auto state = con->get_state(); + if(state == websocketpp::session::state::closed) + std::cout<m_status = WebsocketClient::FAIL; + if (c->m_on_disconnected != nullptr) { + c->m_on_disconnected(c,WebsocketClient::CloseReason::PEER_CLOSED); + } +} - // Note that connect here only requests a connection. No network messages are - // exchanged until the event loop starts running in the next line. - c.connect(con); +WebsocketClient::~WebsocketClient(){ - // Start the ASIO io_service run loop - // this will cause a single connection to be made to the server. c.run() - // will exit when this connection is closed. - c.run(); - } - catch (websocketpp::exception const& e) { - std::cout << e.what() << std::endl; - } -} \ No newline at end of file + this->m_status = WebsocketClient::STOP; + m_client.stop(); + m_thread->join(); +} + +WebsocketClient::WebsocketClient(std::string url,bool tls) +{ + m_tls = tls; + m_auto_reconn = false; + m_url = url; + if(m_tls){ +// Set logging to be pretty verbose (everything except message payloads) + m_client_tls.set_access_channels(websocketpp::log::alevel::all); + m_client_tls.clear_access_channels(websocketpp::log::alevel::frame_payload); + m_client_tls.set_tls_init_handler([this](websocketpp::connection_hdl){ + return websocketpp::lib::make_shared(asio::ssl::context::tlsv1); + }); + // Initialize ASIO + m_client_tls.init_asio(); + m_thread = new std::thread([this]() + { + while (this->m_status != STOP) + { + m_client_tls.set_message_handler(bind(&on_message, this, ::_1, ::_2)); + websocketpp::lib::error_code ec; + std::cout<<"1"<m_url, ec); + m_conn_tls->set_open_handler(websocketpp::lib::bind( + &on_open, + this, + websocketpp::lib::placeholders::_1 + )); + m_conn_tls->set_fail_handler(websocketpp::lib::bind( + &on_fail, + this, + websocketpp::lib::placeholders::_1 + )); + m_conn_tls->set_close_handler(websocketpp::lib::bind( + &on_close, + this, + websocketpp::lib::placeholders::_1 + )); + if (ec) { + std::cout << "could not create connection because: " << ec.message() << std::endl; + this->m_status = Status::FAIL; + } + std::cout<<"2"<get_state() != websocketpp::session::state::open) + std::cout<get_state() <<" websocketpp::session::state "<m_status = WebsocketClient::CONNECTING; + while((this->m_status != WebsocketClient::FAIL) && + (this->m_status != WebsocketClient::CLOSED) + &&(this->m_status != WebsocketClient::STOP) + ){ + try{ + // while(this->m_status == WebsocketClient::CONNECTED){ + int count_of_handler = this->m_client_tls.run(); + // std::cout<<"count_of_handler: " << count_of_handler<m_on_disconnected(this,WebsocketClient::CloseReason::LOCAL_CLOSED); + }); + } + else{ + // Set logging to be pretty verbose (everything except message payloads) + m_client.set_access_channels(websocketpp::log::alevel::all); + m_client.clear_access_channels(websocketpp::log::alevel::frame_payload); + + // Initialize ASIO + this->m_client.init_asio(); + m_thread = new std::thread([this]() + { + while (this->m_status != STOP) + { + this->m_client.set_message_handler(bind(&on_message, this, ::_1, ::_2)); + websocketpp::lib::error_code ec; + std::cout<<"1"<m_url, ec); + m_conn->set_open_handler(websocketpp::lib::bind( + &on_open, + this, + websocketpp::lib::placeholders::_1 + )); + m_conn->set_fail_handler(websocketpp::lib::bind( + &on_fail, + this, + websocketpp::lib::placeholders::_1 + )); + m_conn->set_close_handler(websocketpp::lib::bind( + &on_close, + this, + websocketpp::lib::placeholders::_1 + )); + if (ec) { + std::cout << "could not create connection because: " << ec.message() << std::endl; + this->m_status = Status::FAIL; + } + std::cout<<"2"<m_client.connect(m_conn); + if(ptr->get_state() != websocketpp::session::state::open) + std::cout<get_state() <<" websocketpp::session::state "<m_status = WebsocketClient::CONNECTING; + while((this->m_status != WebsocketClient::FAIL) && + (this->m_status != WebsocketClient::CLOSED) + &&(this->m_status != WebsocketClient::STOP) + ){ + try{ + // while(this->m_status == WebsocketClient::CONNECTED){ + int count_of_handler = this->m_client.run(); + // std::cout<<"count_of_handler: " << count_of_handler<m_on_disconnected(this,WebsocketClient::CloseReason::LOCAL_CLOSED); + + }); + } + +} + +int WebsocketClient::SetOnConnectedHandler(OnConnectedHandler on_connected){ + this->m_on_connected = on_connected; + return 0; +} + +int WebsocketClient::SetOnDisConnectedHandler(OnDisConnectedHandler on_disconnected){ + this->m_on_disconnected = on_disconnected; + return 0; +} + +int WebsocketClient::SetOnReadHandler(OnReadHandler onread){ + this->m_onread = onread; + return 0; +} diff --git a/examples/proto_debuger/websocket_client.h b/examples/proto_debuger/websocket_client.h index 0fc5e7a0..9050e68f 100644 --- a/examples/proto_debuger/websocket_client.h +++ b/examples/proto_debuger/websocket_client.h @@ -1,7 +1,81 @@ +/* + * @Author: your name + * @Date: 2022-02-25 22:06:57 + * @LastEditTime: 2022-03-06 22:42:35 + * @LastEditors: Please set LastEditors + * @Description: 鎵撳紑koroFileHeader鏌ョ湅閰嶇疆 杩涜璁剧疆: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + * @FilePath: \test\websocket_client.h + */ + #pragma once +#include +#include +#include +#include +#include +#include +#include -class WebsocketClient -{ +typedef websocketpp::client Client; +typedef websocketpp::client TlsClient; +using websocketpp::lib::placeholders::_1; +using websocketpp::lib::placeholders::_2; +using websocketpp::lib::bind; + +// pull out the type of messages sent by our config +typedef websocketpp::config::asio_client::message_type::ptr message_ptr; + +class WebsocketClient { +public: + enum CloseReason{ + PEER_CLOSED = 1, + LOCAL_CLOSED = 2 + }; + + typedef std::function OnConnectedHandler; + typedef std::function OnDisConnectedHandler; + typedef std::function OnReadHandler; + + enum Status + { + STOP = 0, + CONNECTING = 1, + CONNECTED = 2, + FAIL = 3, + CLOSED = 4, + }; + + Status State(){ + return m_status; + } + WebsocketClient(std::string url,bool tls); + ~WebsocketClient(); + int SendMsg(const char * str,uint32_t len,websocketpp::frame::opcode::value); + friend void on_fail(WebsocketClient * c, websocketpp::connection_hdl hdl); + friend void on_close(WebsocketClient * c, websocketpp::connection_hdl hdl); + friend void on_open(WebsocketClient * c, websocketpp::connection_hdl hdl); + friend void on_message(WebsocketClient* c, websocketpp::connection_hdl hdl, message_ptr msg); + int SetOnConnectedHandler(OnConnectedHandler on_connected); + int SetOnDisConnectedHandler(OnDisConnectedHandler on_disconnected); + int SetOnReadHandler(OnReadHandler onread); + +private: + uint32_t m_socketfd; + Status m_status; // 褰撳墠鏈嶅姟鍣ㄧ姸鎬 + std::string m_url; // url + Client m_client; // 瀹㈡埛绔 + TlsClient m_client_tls; + std::thread *m_thread; // 褰撳墠娲诲姩绾跨▼ + Client::connection_ptr m_conn; + TlsClient::connection_ptr m_conn_tls; // 瀹㈡埛绔 + + bool m_auto_reconn; + bool m_tls; + OnReadHandler m_onread; + OnConnectedHandler m_on_connected; + OnDisConnectedHandler m_on_disconnected; }; + + diff --git a/examples/proto_debuger/websocket_client_form.cpp b/examples/proto_debuger/websocket_client_form.cpp index d30ad9df..4f4018f3 100644 --- a/examples/proto_debuger/websocket_client_form.cpp +++ b/examples/proto_debuger/websocket_client_form.cpp @@ -21,6 +21,8 @@ void WebsocketClientForm::Init() m_check_box_4 = dynamic_cast(FindSubControl(L"check_hex_recv")); m_btn_save_lua = dynamic_cast(FindSubControl(L"btn_save_lua")); m_btn_close_form = dynamic_cast(FindSubControl(L"btn_close_uart")); + + } LuaDelegate* WebsocketClientForm::LuaVM() diff --git a/examples/proto_debuger/websocket_client_form.h b/examples/proto_debuger/websocket_client_form.h index 249b8203..ff4b4146 100644 --- a/examples/proto_debuger/websocket_client_form.h +++ b/examples/proto_debuger/websocket_client_form.h @@ -23,11 +23,7 @@ public: WebsocketClientForm(ui::Window* hwnd, string url, uint32_t port, TcpClientLibevent* p); ~WebsocketClientForm(); virtual void Init() override; - - - LuaDelegate* LuaVM(); - private: ui::Label* m_label_1; ui::RichEdit* m_rich_edit_1; diff --git a/examples/proto_debuger/websocket_server.cpp b/examples/proto_debuger/websocket_server.cpp new file mode 100644 index 00000000..ff60d0c4 --- /dev/null +++ b/examples/proto_debuger/websocket_server.cpp @@ -0,0 +1,97 @@ +#include "websocket_server.h" + +// Define a callback to handle new connection income +void on_new_connection(WebsocketServer* s, websocketpp::connection_hdl hdl){ + std::cout << "on new connection\r\n"; + WsServer::connection_ptr con = s->m_server->get_con_from_hdl(hdl); + auto socket = con->get_raw_socket().native_handle(); + s->m_clients[socket] = hdl; + auto addr = con->get_socket().remote_endpoint().address(); + auto host = con->get_host(); + auto uri = con->get_uri(); + auto resource = con->get_resource(); + std::cout<m_server->get_con_from_hdl(hdl); + auto socket = con->get_raw_socket().native_handle(); + s->m_clients.erase(socket); +} + +// Define a callback to handle incoming messages +void on_message(WebsocketServer* s, websocketpp::connection_hdl hdl, message_ptr msg) { + std::cout << "on_message called with hdl: " << hdl.lock().get() + << " and message: " << msg->get_payload() + << std::endl; + + // check for a special command to instruct the server to stop listening so + // it can be cleanly exited. + if (msg->get_payload() == "stop-listening") { + s->m_server->stop_listening(); + return; + } + try { + s->m_server->send(hdl, msg->get_payload(), msg->get_opcode()); + + } catch (websocketpp::exception const & e) { + std::cout << "Echo failed because: " + << "(" << e.what() << ")" << std::endl; + } +} + +WebsocketServer::WebsocketServer(std::string server,uint32_t port){ + m_port = port; + m_server = new WsServer; + m_thread = new std::thread([this](){ + // Set logging settings + m_server->set_access_channels(websocketpp::log::alevel::all); + m_server->clear_access_channels(websocketpp::log::alevel::frame_payload); + // Initialize Asio + m_server->init_asio(); + // Register our message handler + m_server->set_open_handler(std::bind(&on_new_connection,this,::_1)); + m_server->set_message_handler(std::bind(&on_message,this,::_1,::_2)); + m_server->set_close_handler(std::bind(&on_connection_close,this,::_1)); + m_server->listen(m_port); + // Start the server accept loop + m_server->start_accept(); + // Start the ASIO io_service run loop + m_server->run(); + }); +} + +int WebsocketServer::SendData(uint32_t fd,const char* dat,int len, + websocketpp::frame::opcode::value op){ + + auto itr = this->m_clients.find(fd); + if(itr != m_clients.end()){ + std::error_code err; + WsServer::connection_ptr con = m_server->get_con_from_hdl(itr->second); + m_server->send(itr->second,dat,len,op,err); + if(err.message() != ""){ + std::cout<<"websocket error" << err.message()<get_con_from_hdl(itr->second); + m_server->send(itr->second,dat,len, opcode,err); + if(err.message() != ""){ + std::cout<<"websocket error" << err.message()< +#include +#include +#include +#include +#include +#include + +typedef websocketpp::server WsServer; + + +using websocketpp::lib::placeholders::_1; +using websocketpp::lib::placeholders::_2; +using websocketpp::lib::bind; +typedef WsServer::message_ptr message_ptr; + + +class WebsocketServer { +public: + WebsocketServer(std::string server,uint32_t port); + friend void on_new_connection(WebsocketServer* s, websocketpp::connection_hdl hdl); + friend void on_message(WebsocketServer* s, websocketpp::connection_hdl hdl, message_ptr msg); + friend void on_connection_close(WebsocketServer* s, websocketpp::connection_hdl hdl); + int SendData(uint32_t,const char *data,int len,websocketpp::frame::opcode::value); + int SendDataAllClient(const char *data,int len,websocketpp::frame::opcode::value); + +private: + std::string m_url; // 鍦板潃 + uint32_t m_port; // url + WsServer *m_server; + std::thread *m_thread; + std::mutex m_mutex; + std::map m_clients; +}; + +