中间件底层,websocket

WebSocketServer.h 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #pragma once
  2. #pragma warning(disable : 4996)
  3. #include <websocketpp/config/asio.hpp>
  4. #include <websocketpp/server.hpp>
  5. #include <websocketpp/common/thread.hpp>
  6. #include <websocketpp/common/memory.hpp>
  7. #include <boost/bind.hpp>
  8. #include <functional>
  9. #include <iostream>
  10. #include <string>
  11. #include <codecvt>
  12. #include <thread>
  13. #include <unordered_map>
  14. #include <mutex>
  15. #include <regex>
  16. #include <json/json.h>
  17. #pragma comment(lib,"libssl.lib")
  18. #pragma comment(lib,"libcrypto.lib")
  19. #pragma comment(lib,"Crypt32.lib")
  20. //using namespace std;
  21. typedef websocketpp::server<websocketpp::config::asio> server_plain;
  22. typedef websocketpp::server<websocketpp::config::asio_tls> server_tls;
  23. typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
  24. enum WEBSOCKET_TYPE
  25. {
  26. NORMAL = 0,
  27. TLS = 1,
  28. };
  29. class CWebSocketServer
  30. {
  31. public:
  32. CWebSocketServer();
  33. ~CWebSocketServer();
  34. bool init(uint16_t port ,uint16_t tlsPort ,std::string sslFile,std::string sslPwd);
  35. bool sendMsg(websocketpp::connection_hdl hdl, std::string msg);
  36. bool sendMsg(long conID, std::string msg);
  37. void run();
  38. void asyncRun();
  39. void close(websocketpp::connection_hdl hdl); // 关闭与指定客户端的连接
  40. void stop();
  41. //typedef std::function<void(websocketpp::connection_hdl hdl,const std::string &msg, const std::string &ip)> Callback_RecvMsg;
  42. //typedef std::function<void(websocketpp::connection_hdl hdl)> Callback_Close;
  43. typedef std::function<void(const long conID, const std::string &, const std::string &)> Callback_RecvMsg;
  44. typedef std::function<void(const long)> Callback_Close;
  45. void setCallbackRecvMsg(Callback_RecvMsg pRecvFun) { this->pRecvFun = pRecvFun; };
  46. void setCallbackClose(Callback_Close pCloseFun) { this->pCloseFun = pCloseFun; };
  47. private:
  48. template <typename EndpointType>
  49. void on_open(EndpointType* s, websocketpp::connection_hdl hdl, WEBSOCKET_TYPE type) {
  50. const long conID = reinterpret_cast<long>(hdl.lock().get());
  51. std::unique_lock<std::mutex>lock(m_mut);
  52. m_servers.insert(std::make_pair(hdl.lock().get(), type));
  53. m_conIds.insert(std::make_pair(conID,hdl));
  54. }
  55. template <typename EndpointType>
  56. void on_close(EndpointType* s, websocketpp::connection_hdl hdl, WEBSOCKET_TYPE type) {
  57. const long conID = reinterpret_cast<long>(hdl.lock().get());
  58. if (this->pCloseFun != nullptr)
  59. this->pCloseFun(conID); // 连接断开回调函数
  60. std::unique_lock<std::mutex>lock(m_mut);
  61. m_servers.erase(hdl.lock().get());
  62. m_conIds.erase(conID);
  63. }
  64. template <typename EndpointType>
  65. void on_message(EndpointType* s, websocketpp::connection_hdl hdl, typename EndpointType::message_ptr msg) {
  66. const long conID = reinterpret_cast<long>(hdl.lock().get());
  67. const std::string msgInfo = std::move(msg->get_payload());
  68. const std::string str = std::regex_replace(s->get_con_from_hdl(hdl)->get_remote_endpoint(), std::regex("::ffff:"),"");
  69. if (this->pRecvFun != nullptr && !msgInfo.empty())
  70. this->pRecvFun(conID, msgInfo, str); // 收到消息回调函数
  71. }
  72. std::string get_password() {
  73. return m_sslPwd;
  74. }
  75. /*context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
  76. std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
  77. context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23_server);
  78. try {
  79. ctx->set_options(boost::asio::ssl::context::default_workarounds |
  80. boost::asio::ssl::context::no_sslv2 |
  81. boost::asio::ssl::context::no_sslv3 |
  82. boost::asio::ssl::context::single_dh_use);
  83. ctx->set_password_callback(bind(&CWebSocketServer::get_password,this));
  84. ctx->use_certificate_chain_file(m_sslFile);
  85. ctx->use_private_key_file(m_sslFile, boost::asio::ssl::context::pem);
  86. }
  87. catch (std::exception& e) {
  88. char str[1024];
  89. snprintf(str, 1024, "[%s :%d][ %s]", __FUNCTION__, __LINE__, e.what());
  90. std::cout << str << std::endl;
  91. }
  92. return ctx;
  93. }*/
  94. context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
  95. std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
  96. context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv13_server);
  97. try {
  98. ctx->set_options(boost::asio::ssl::context::default_workarounds |
  99. boost::asio::ssl::context::no_sslv2 |
  100. boost::asio::ssl::context::no_sslv3 |
  101. boost::asio::ssl::context::no_tlsv1 |
  102. boost::asio::ssl::context::single_dh_use);
  103. //ctx->set_password_callback(bind(&CWebSocketServer::get_password, this));
  104. //ctx->use_certificate_chain_file(m_sslFile);
  105. ctx->use_certificate_file(m_sslFile, boost::asio::ssl::context::pem); // "server.crt"
  106. ctx->use_private_key_file(m_sslPwd, boost::asio::ssl::context::pem); // "server.key"
  107. }
  108. catch (std::exception& e) {
  109. char str[1024];
  110. snprintf(str, 1024, "[%s :%d][ %s]", __FUNCTION__, __LINE__, e.what());
  111. std::cout << str << std::endl;
  112. }
  113. return ctx;
  114. }
  115. // 注释:多字节包括GBK和UTF-8
  116. //UTF-8 GBK
  117. int UTF82GBK(char *szUtf8, char *szGbk, int Len)
  118. {
  119. int n = MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, NULL, 0);
  120. WCHAR * wszGBK = new WCHAR[sizeof(WCHAR) * n];
  121. memset(wszGBK, 0, sizeof(WCHAR) * n);
  122. MultiByteToWideChar(CP_UTF8, 0, szUtf8, -1, wszGBK, n);
  123. n = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
  124. if (n > Len)
  125. {
  126. delete[]wszGBK;
  127. wszGBK = NULL;
  128. return -1;
  129. }
  130. WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGbk, n, NULL, NULL);
  131. delete[]wszGBK;
  132. wszGBK = NULL;
  133. return 0;
  134. }
  135. // GBK UTF8
  136. static void ConvertGBKToUtf8(std::string &gbk)
  137. {
  138. CString strGBK = gbk.c_str();
  139. int len = MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strGBK, -1, NULL, 0);
  140. wchar_t * wszUtf8 = new wchar_t[len];
  141. memset(wszUtf8, 0, len);
  142. MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strGBK, -1, wszUtf8, len);
  143. len = WideCharToMultiByte(CP_UTF8, 0, wszUtf8, -1, NULL, 0, NULL, NULL);
  144. char *szUtf8 = new char[len + 1];
  145. memset(szUtf8, 0, len + 1);
  146. WideCharToMultiByte(CP_UTF8, 0, wszUtf8, -1, szUtf8, len, NULL, NULL);
  147. gbk = szUtf8;
  148. delete[] szUtf8; szUtf8 = NULL;
  149. delete[] wszUtf8; wszUtf8 = NULL;
  150. }
  151. static std::wstring string_to_wstring(const std::string &s)
  152. {
  153. using default_convert = std::codecvt<wchar_t, char, std::mbstate_t>;
  154. static std::wstring_convert<default_convert>conv(new default_convert("CHS"));
  155. return conv.from_bytes(s);
  156. }
  157. static std::string ansi_to_utf8(const std::string &s)
  158. {
  159. static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
  160. return conv.to_bytes(string_to_wstring(s));
  161. }
  162. static std::string wstring_to_string(const std::wstring &s)
  163. {
  164. using default_convert = std::codecvt<wchar_t, char, std::mbstate_t>;
  165. static std::wstring_convert<default_convert>conv(new default_convert("CHS"));
  166. return conv.to_bytes(s);
  167. }
  168. static std::string utf8_to_ansi(const std::string& s)
  169. {
  170. static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
  171. return wstring_to_string(conv.from_bytes(s));
  172. }
  173. private:
  174. boost::asio::io_service ios;
  175. websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_Thread; // 线程
  176. server_plain endpoint_plain;
  177. server_tls endpoint_tls;
  178. std::string m_sslFile;
  179. std::string m_sslPwd;
  180. std::unordered_map<void*, WEBSOCKET_TYPE> m_servers;
  181. std::unordered_map<long, websocketpp::connection_hdl> m_conIds;
  182. std::mutex m_mut; //map锁
  183. Callback_RecvMsg pRecvFun; // 接收消息回调函数
  184. Callback_Close pCloseFun; // 连接断开回调函数
  185. };