#pragma once #pragma warning(disable : 4996) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma comment(lib,"libssl.lib") #pragma comment(lib,"libcrypto.lib") #pragma comment(lib,"Crypt32.lib") //using namespace std; typedef websocketpp::server server_plain; typedef websocketpp::server server_tls; typedef websocketpp::lib::shared_ptr context_ptr; enum WEBSOCKET_TYPE { NORMAL = 0, TLS = 1, }; class CWebSocketServer { public: CWebSocketServer(); ~CWebSocketServer(); bool init(uint16_t port ,uint16_t tlsPort ,std::string sslFile,std::string sslPwd); bool sendMsg(websocketpp::connection_hdl hdl, std::string msg); bool sendMsg(long conID, std::string msg); void run(); void asyncRun(); void close(websocketpp::connection_hdl hdl); // 关闭与指定客户端的连接 void stop(); //typedef std::function Callback_RecvMsg; //typedef std::function Callback_Close; typedef std::function Callback_RecvMsg; typedef std::function Callback_Close; void setCallbackRecvMsg(Callback_RecvMsg pRecvFun) { this->pRecvFun = pRecvFun; }; void setCallbackClose(Callback_Close pCloseFun) { this->pCloseFun = pCloseFun; }; private: template void on_open(EndpointType* s, websocketpp::connection_hdl hdl, WEBSOCKET_TYPE type) { const long conID = reinterpret_cast(hdl.lock().get()); std::unique_locklock(m_mut); m_servers.insert(std::make_pair(hdl.lock().get(), type)); m_conIds.insert(std::make_pair(conID,hdl)); } template void on_close(EndpointType* s, websocketpp::connection_hdl hdl, WEBSOCKET_TYPE type) { const long conID = reinterpret_cast(hdl.lock().get()); if (this->pCloseFun != nullptr) this->pCloseFun(conID); // 连接断开回调函数 std::unique_locklock(m_mut); m_servers.erase(hdl.lock().get()); m_conIds.erase(conID); } template void on_message(EndpointType* s, websocketpp::connection_hdl hdl, typename EndpointType::message_ptr msg) { const long conID = reinterpret_cast(hdl.lock().get()); const std::string msgInfo = std::move(msg->get_payload()); const std::string str = std::regex_replace(s->get_con_from_hdl(hdl)->get_remote_endpoint(), std::regex("::ffff:"),""); if (this->pRecvFun != nullptr && !msgInfo.empty()) this->pRecvFun(conID, msgInfo, str); // 收到消息回调函数 } std::string get_password() { return m_sslPwd; } /*context_ptr on_tls_init(websocketpp::connection_hdl hdl) { std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl; context_ptr ctx = websocketpp::lib::make_shared(boost::asio::ssl::context::sslv23_server); try { ctx->set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::single_dh_use); ctx->set_password_callback(bind(&CWebSocketServer::get_password,this)); ctx->use_certificate_chain_file(m_sslFile); ctx->use_private_key_file(m_sslFile, boost::asio::ssl::context::pem); } catch (std::exception& e) { char str[1024]; snprintf(str, 1024, "[%s :%d][ %s]", __FUNCTION__, __LINE__, e.what()); std::cout << str << std::endl; } return ctx; }*/ context_ptr on_tls_init(websocketpp::connection_hdl hdl) { std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl; context_ptr ctx = websocketpp::lib::make_shared(boost::asio::ssl::context::tlsv13_server); try { ctx->set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::single_dh_use); //ctx->set_password_callback(bind(&CWebSocketServer::get_password, this)); //ctx->use_certificate_chain_file(m_sslFile); ctx->use_certificate_file(m_sslFile, boost::asio::ssl::context::pem); // "server.crt" ctx->use_private_key_file(m_sslPwd, boost::asio::ssl::context::pem); // "server.key" } catch (std::exception& e) { char str[1024]; snprintf(str, 1024, "[%s :%d][ %s]", __FUNCTION__, __LINE__, e.what()); std::cout << str << std::endl; } return ctx; } // 注释:多字节包括GBK和UTF-8 //UTF-8 GBK int UTF82GBK(char *szUtf8, char *szGbk, int Len) { int n = MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, NULL, 0); WCHAR * wszGBK = new WCHAR[sizeof(WCHAR) * n]; memset(wszGBK, 0, sizeof(WCHAR) * n); MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, wszGBK, n); n = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL); if (n > Len) { delete[]wszGBK; wszGBK = NULL; return -1; } WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGbk, n, NULL, NULL); delete[]wszGBK; wszGBK = NULL; return 0; } // GBK UTF8 static void ConvertGBKToUtf8(std::string &gbk) { CString strGBK = gbk.c_str(); int len = MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strGBK, -1, NULL, 0); wchar_t * wszUtf8 = new wchar_t[len]; memset(wszUtf8, 0, len); MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strGBK, -1, wszUtf8, len); len = WideCharToMultiByte(CP_UTF8, 0, wszUtf8, -1, NULL, 0, NULL, NULL); char *szUtf8 = new char[len + 1]; memset(szUtf8, 0, len + 1); WideCharToMultiByte(CP_UTF8, 0, wszUtf8, -1, szUtf8, len, NULL, NULL); gbk = szUtf8; delete[] szUtf8; szUtf8 = NULL; delete[] wszUtf8; wszUtf8 = NULL; } static std::wstring string_to_wstring(const std::string &s) { using default_convert = std::codecvt; static std::wstring_convertconv(new default_convert("CHS")); return conv.from_bytes(s); } static std::string ansi_to_utf8(const std::string &s) { static std::wstring_convert > conv; return conv.to_bytes(string_to_wstring(s)); } static std::string wstring_to_string(const std::wstring &s) { using default_convert = std::codecvt; static std::wstring_convertconv(new default_convert("CHS")); return conv.to_bytes(s); } static std::string utf8_to_ansi(const std::string& s) { static std::wstring_convert > conv; return wstring_to_string(conv.from_bytes(s)); } private: boost::asio::io_service ios; websocketpp::lib::shared_ptr m_Thread; // 线程 server_plain endpoint_plain; server_tls endpoint_tls; std::string m_sslFile; std::string m_sslPwd; std::unordered_map m_servers; std::unordered_map m_conIds; std::mutex m_mut; //map锁 Callback_RecvMsg pRecvFun; // 接收消息回调函数 Callback_Close pCloseFun; // 连接断开回调函数 };