当前位置:   article > 正文

C++ websocketpp库 源码编译及使用(VS2019)_websocketpp编译

websocketpp编译

源码编译

下载源码

git clone git@github.com:zaphoyd/websocketpp.git

如果打不开可以试试:

git clone git@gitee.com:epson/websocketpp.git

添加websocketpp文件加到包含目录中

OpenSSL

关于OpenSSL编译,参看:

C++ OpenSSL库 源码编译及使用(VS2019)_道-CSDN博客

这里需要用到openssl 1.1.1版本,最新3.0版本会报错。

Boost库

关于Boost编译,参看:

C++ boost库 源码编译及使用(VS2019)_道-CSDN博客

加入包含目录

 

加入库目录

 

简单测试

  1. #include <iostream>
  2. #include <websocketpp/config/asio_client.hpp>
  3. #include <websocketpp/client.hpp>
  4. #ifndef _DEBUG
  5. #ifdef _WIN64
  6. #pragma comment (lib,"x64/Release/libcrypto.lib")
  7. #pragma comment (lib,"x64/Release/libssl.lib")
  8. #else
  9. #pragma comment (lib,"x86/Release/libcrypto.lib")
  10. #pragma comment (lib,"x86/Release/libssl.lib")
  11. #endif // _WIN64
  12. #else
  13. #ifdef _WIN64
  14. #pragma comment (lib,"x64/Debug/libcrypto.lib")
  15. #pragma comment (lib,"x64/Debug/libssl.lib")
  16. #else
  17. #pragma comment (lib,"x86/Debug/libcrypto.lib")
  18. #pragma comment (lib,"x86/Debug/libssl.lib")
  19. #endif // _WIN64
  20. #endif
  21. typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
  22. typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;
  23. using websocketpp::lib::placeholders::_1;
  24. using websocketpp::lib::placeholders::_2;
  25. using websocketpp::lib::bind;
  26. client m_ws;
  27. /// Verify that one of the subject alternative names matches the given hostname
  28. bool verify_subject_alternative_name(const char* hostname, X509* cert) {
  29. STACK_OF(GENERAL_NAME)* san_names = NULL;
  30. san_names = (STACK_OF(GENERAL_NAME)*) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
  31. if (san_names == NULL) {
  32. return false;
  33. }
  34. int san_names_count = sk_GENERAL_NAME_num(san_names);
  35. bool result = false;
  36. for (int i = 0; i < san_names_count; i++) {
  37. const GENERAL_NAME* current_name = sk_GENERAL_NAME_value(san_names, i);
  38. if (current_name->type != GEN_DNS) {
  39. continue;
  40. }
  41. char const* dns_name = (char const*)ASN1_STRING_get0_data(current_name->d.dNSName);
  42. // Make sure there isn't an embedded NUL character in the DNS name
  43. if (ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
  44. break;
  45. }
  46. // Compare expected hostname with the CN
  47. result = (strcmp(hostname, dns_name) == 0);
  48. }
  49. sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
  50. return result;
  51. }
  52. /// Verify that the certificate common name matches the given hostname
  53. bool verify_common_name(char const* hostname, X509* cert) {
  54. // Find the position of the CN field in the Subject field of the certificate
  55. int common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name(cert), NID_commonName, -1);
  56. if (common_name_loc < 0) {
  57. return false;
  58. }
  59. // Extract the CN field
  60. X509_NAME_ENTRY* common_name_entry = X509_NAME_get_entry(X509_get_subject_name(cert), common_name_loc);
  61. if (common_name_entry == NULL) {
  62. return false;
  63. }
  64. // Convert the CN field to a C string
  65. ASN1_STRING* common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
  66. if (common_name_asn1 == NULL) {
  67. return false;
  68. }
  69. char const* common_name_str = (char const*)ASN1_STRING_get0_data(common_name_asn1);
  70. // Make sure there isn't an embedded NUL character in the CN
  71. if (ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
  72. return false;
  73. }
  74. // Compare expected hostname with the CN
  75. return (strcmp(hostname, common_name_str) == 0);
  76. }
  77. bool verify_certificate(const char* hostname, bool preverified, boost::asio::ssl::verify_context& ctx) {
  78. // The verify callback can be used to check whether the certificate that is
  79. // being presented is valid for the peer. For example, RFC 2818 describes
  80. // the steps involved in doing this for HTTPS. Consult the OpenSSL
  81. // documentation for more details. Note that the callback is called once
  82. // for each certificate in the certificate chain, starting from the root
  83. // certificate authority.
  84. // Retrieve the depth of the current cert in the chain. 0 indicates the
  85. // actual server cert, upon which we will perform extra validation
  86. // (specifically, ensuring that the hostname matches. For other certs we
  87. // will use the 'preverified' flag from Asio, which incorporates a number of
  88. // non-implementation specific OpenSSL checking, such as the formatting of
  89. // certs and the trusted status based on the CA certs we imported earlier.
  90. int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle());
  91. // if we are on the final cert and everything else checks out, ensure that
  92. // the hostname is present on the list of SANs or the common name (CN).
  93. if (depth == 0 && preverified) {
  94. X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
  95. if (verify_subject_alternative_name(hostname, cert)) {
  96. return true;
  97. }
  98. else if (verify_common_name(hostname, cert)) {
  99. return true;
  100. }
  101. else {
  102. return false;
  103. }
  104. }
  105. return preverified;
  106. }
  107. context_ptr on_tls_init(const char* hostname, websocketpp::connection_hdl) {
  108. context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
  109. try {
  110. ctx->set_options(boost::asio::ssl::context::default_workarounds |
  111. boost::asio::ssl::context::no_sslv2 |
  112. boost::asio::ssl::context::no_sslv3 |
  113. boost::asio::ssl::context::single_dh_use);
  114. ctx->set_verify_mode(boost::asio::ssl::verify_none);
  115. //ctx->set_verify_mode(boost::asio::ssl::verify_peer);
  116. ctx->set_verify_callback(bind(&verify_certificate, hostname, ::_1, ::_2));
  117. // Here we load the CA certificates of all CA's that this client trusts.
  118. //CString str;
  119. //str.Format("%sca-chain.cert.pem", theApp.m_lpszAppPath);
  120. //ctx->load_verify_file(str.GetBufferSetLength(str.GetLength()+1));
  121. }
  122. catch (std::exception& e) {
  123. std::cout << e.what() << std::endl;
  124. }
  125. return ctx;
  126. }
  127. void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
  128. std::cout << msg->get_payload() << std::endl;
  129. }
  130. void on_fail(websocketpp::connection_hdl hdl) {
  131. std::cout << "on_fail" <<std::endl;
  132. }
  133. void on_open(websocketpp::connection_hdl hdl) {
  134. std::cout << "on_open" << std::endl;
  135. m_ws.send(hdl, "{\"cmd\":\"get_secret_no\"}", websocketpp::frame::opcode::text);
  136. }
  137. void on_close(websocketpp::connection_hdl) {
  138. std::cout << "on_close" << std::endl;
  139. }
  140. int main()
  141. {
  142. std::string hostname = "openhw.work.weixin.qq.com";
  143. std::string port = "443";
  144. std::string uri = "wss://" + hostname + ":" + port;
  145. try {
  146. // Set logging to be pretty verbose (everything except message payloads)
  147. m_ws.set_access_channels(websocketpp::log::alevel::all);
  148. m_ws.clear_access_channels(websocketpp::log::alevel::frame_payload);
  149. m_ws.set_error_channels(websocketpp::log::elevel::all);
  150. // Initialize ASIO
  151. m_ws.init_asio();
  152. // Register our message handler
  153. m_ws.set_tls_init_handler(bind(&on_tls_init, hostname.c_str(), ::_1));
  154. m_ws.set_message_handler(&on_message);
  155. m_ws.set_open_handler(&on_open);
  156. m_ws.set_close_handler(&on_close);
  157. m_ws.set_fail_handler(&on_fail);
  158. websocketpp::lib::error_code ec;
  159. client::connection_ptr con = m_ws.get_connection(uri, ec);
  160. if (ec) {
  161. std::cout << ec.message() << std::endl;
  162. }
  163. // Note that connect here only requests a connection. No network messages are
  164. // exchanged until the event loop starts running in the next line.
  165. m_ws.connect(con);
  166. m_ws.get_alog().write(websocketpp::log::alevel::app, "Connecting to " + uri);
  167. // Start the ASIO io_service run loop
  168. // this will cause a single connection to be made to the server. c.run()
  169. // will exit when this connection is closed.
  170. m_ws.run();
  171. }
  172. catch (websocketpp::exception const& e) {
  173. std::cout << e.what() << std::endl;
  174. }
  175. }

运行结果:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/241864
推荐阅读
相关标签
  

闽ICP备14008679号