websocketpp上手笔记-Windows安装

WebSocketpp是什么

最近手上有一个c++项目,需要用websocket从服务器端收内容。于是网上找了圈,发现WebSocketpp库可以做websocket的客户端。

WebSocketpp也叫WebSocket++,github地址是:https://github.com/zaphoyd/websocketpp,6.7k Stars。最新版本0.8.2.

话不多少,先把代码从github上拉下来。查看README,找到UserManual,进入Getting Started。文档中如此描述:

WebSocket++ is a header only library. You can start using it by including the websocketpp source directory in your project's include path and including the appropriate WebSocket++ headers in your program. You may also need to include and/or link to appropriate Boost/system libraries. 

WebSocket++ includes cmake and scons scripts for building the examples and unit tests.

WebSocket++是一个只需要头文件的库,直接包含在到工程中就可以使用了。但是呢,还需要Boost库。

WebSocket++包含了cmake脚本来编译examples和unit tests。

我的目标就是编译成功examples和unit tests。

 查看WebSocketpp的CMakeLists.txt

WebSocketpp支持cmake脚本呢编译examples和tests。于是先查看CMakeLists.txt。迅速看到了依赖内容Dependencies,里面明确提到了要依赖Boost库。由于我之前没有使用过boost库,所以得先安装boost库。

由于我的程序同事支持Windows和Linux,所以两个平台都要安装。

安装Boost

首先从官网https://www.boost.org/users/download/下载boost源码。我没有想太多,直接下载的最新版本1.84.0,直觉感觉WebSocketpp未必能支持这么新的版本。先硬着头皮试试,不行再换低版本。

进入到boost源码目录,打开vs2019的命令行,先执行:

bootstrap.bat

执行完成之后,会生成一个b2.exe的可执行文件。接着执行:

.\b2 variant=debug link=static threading=multi runtime-link=static

参数含义:

  • variant=debug   编译Debug
  • link=static   静态库
  • threading=multi支持多线程
  • runtime-link=static  静态连接

也就是我要编译一个使用MTD运行库的debug版本的静态库。没有指定编译目录,默认本文件夹。

编译完成之后输出:

The Boost C++ Libraries were successfully built!

The following directory should be added to compiler include paths:

    E:\boost_1_84_0

The following directory should be added to linker library paths:

    E:\boost_1_84_0\stage\lib

先试试debug版本能不能用,如果可以,后续再编译Release版本。

尝试WebSocket++能否连接Boost(Debug)

再次进入WebSocket++的CMakeLists.txt文件,找到加载Boost的部分:

    set (Boost_ADDITIONAL_VERSIONS "1.39.0" "1.40.0" "1.41.0" "1.42.0" "1.43.0" "1.44.0" "1.46.1") # todo: someone who knows better spesify these!

    find_package (Boost 1.39.0 COMPONENTS "${WEBSOCKETPP_BOOST_LIBS}")

    if (Boost_FOUND)
        # Boost is a project wide global dependency.
        include_directories (${Boost_INCLUDE_DIRS})
        link_directories (${Boost_LIBRARY_DIRS})

        # Pretty print status
        message (STATUS "-- Include Directories")
        foreach (include_dir ${Boost_INCLUDE_DIRS})
            message (STATUS "       " ${include_dir})
        endforeach ()
        message (STATUS "-- Library Directories")
        foreach (library_dir ${Boost_LIBRARY_DIRS})
            message (STATUS "       " ${library_dir})
        endforeach ()
        message (STATUS "-- Libraries")
        foreach (boost_lib ${Boost_LIBRARIES})
            message (STATUS "       " ${boost_lib})
        endforeach ()
        message ("")
    else ()
        message (FATAL_ERROR "Failed to find required dependency: boost")
    endif ()

把Boost的版本号修改为:1.84.0

 set (Boost_ADDITIONAL_VERSIONS "1.84.0" "1.39.0" "1.40.0" "1.41.0" "1.42.0" "1.43.0" "1.44.0" "1.46.1") # todo: someone who knows better spesify these!

 find_package (Boost 1.84.0 COMPONENTS "${WEBSOCKETPP_BOOST_LIBS}")

开始生成,首先在WebSocket++根目录下创建一个build目录,进入build目录,执行:

cmake .. -DBUILD_EXAMPLES=TRUE -DBUILD_TESTS=TRUE  -DBOOST_ROOT=E:\boost_1_84_0 -DCMAKE_BUILD_TYPE=debug

执行失败,找不到Boost:

e:\websocketpp-master\build>cmake .. -DBUILD_EXAMPLES=TRUE -DBUILD_TESTS=TRUE  -DBOOST_ROOT=E:\boost_1_84_0 -DCMAKE_BUILD_TYPE=debug
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.18362.
* Configuring Boost
-- -- Using BOOST_ROOT
--        E:\boost_1_84_0
CMake Warning at C:/Program Files/CMake/share/cmake-3.20/Modules/FindBoost.cmake:1354 (message):
  New Boost version may have incorrect or missing dependencies and imported
  targets
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.20/Modules/FindBoost.cmake:1476 (_Boost_COMPONENT_DEPENDENCIES)
  C:/Program Files/CMake/share/cmake-3.20/Modules/FindBoost.cmake:2086 (_Boost_MISSING_DEPENDENCIES)
  CMakeLists.txt:218 (find_package)

从网上搜索错误信息“New Boost version may have incorrect or missing dependencies and imported targets”。原因是cmake版本比boost版本旧,如果想使用特定版本的boost,就得使用在该boost发布后发布的cmake版本。

详见:https://stackoverflow.com/questions/65560775/cmake-new-boost-version-may-have-incorrect-or-missing-dependencies-and-importe 我的cmake版本是3.20.3,查看FindBoost.cmake的1354行:

if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0 AND NOT Boost_NO_WARN_NEW_VERSIONS)
    message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
endif()

可以看到该版本的cmake最多支持1.77.0的Boost。不打算安装新版本的cmake,我本来就怀疑WebSocket++不支持Boost1.84.0,趁此机会使用一个确定可用的版本。在github上的Issues上https://github.com/zaphoyd/websocketpp/issues/912,作者回复到:

0.8.2 has been tested through Boost 1.72

所以,也不折腾Boost版本了,下载Boost1.72,重新生成vs工程。这次生成工程成功。然后使用vs2019打开工程,分别编译examples里面的echo_client和echo_server,编译时把运行库改为MTD,与Boost库保持一致。编译成功。

同时启动echo_client和echo_server,也成功,可以运行。

TODO:这里有一个疑问,只指定了boost库的路径,并没有设置要链接哪些boost库,vs是怎么链接到正确的库呢?

SSL

首先,在编译examples的是没有链接openssl的,肯定不支持的。但是,我决定先从代码层面上支持SSL。在CMakeLists中,是使用find_package加载openssl的,但是我电脑上没有没有openssl的cmake module。不过我有已经编译好的open ssl 静态库。于是把静态库copy到WebSocketPP文件夹中。然后手动修改了一下CMakeList.txt:

	#原来是用find_package来设置openssl的,现在改成手动添加OpenSSL的路径
    #find_package(OpenSSL)   
    set(OPENSSL_SSL_LIBRARY "libssl.lib")
	set(OPENSSL_CRYPTO_LIBRARY "libcrypto.lib")
	set(OPENSSL_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/openssl/include")	
	#添加openssl路径
	link_directories(${PROJECT_SOURCE_DIR}/openssl/win64_static)
	
	#设置变量OpenSSL_FOUND,后续会根据该标志来创建TLS的工程
	set(OPENSSL_FOUND ON)

然后重新cmake生成工程,可以看到,生成了print_client_tls。编译成功。在运行之前,我先看了一下大致的逻辑。print_client_tls默认的连接地址是echo_server_tls的地址。echo_server_tls默认使用的一个自签署的证书,print_client_tls使用提前生成的pem文件来验证。

但是,我想用一个有效的网址,采用根证书验证。于是,我把地址改为了:wss://echo.websocket.org。验证部分的代码也要做相应的调整:

void add_windows_root_certs(context_ptr ctx)
{    
    HCERTSTORE hStore = CertOpenSystemStoreA(0, "ROOT");
    if (hStore == NULL) {
        return;
    }

    X509_STORE* store = X509_STORE_new();
    PCCERT_CONTEXT pContext = NULL;
    while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
        X509* x509 = d2i_X509(NULL,
            (const unsigned char**)&pContext->pbCertEncoded,
            pContext->cbCertEncoded);
        if (x509 != NULL) {
            X509_STORE_add_cert(store, x509);
            X509_free(x509);
        }
    }

    CertFreeCertificateContext(pContext);
    CertCloseStore(hStore, 0);

    SSL_CTX_set_cert_store(ctx->native_handle(), store);
}

context_ptr on_tls_init(const char * hostname, websocketpp::connection_hdl) {
    context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);

    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_verify_mode(boost::asio::ssl::verify_peer);
        //设置verify_none就不要验证服务端,也不需要加载证书
        //ctx->set_verify_mode(boost::asio::ssl::verify_none);
        //ctx->set_verify_callback(bind(&verify_certificate, hostname, ::_1, ::_2));
        ctx->set_verify_callback(bind(&verify_certificate, "hostname", ::_1, ::_2));
   
 #ifndef _WIN32
           //这个方法在windows上不起作用
        ctx->set_default_verify_paths();
#else
        //加载系统的根证书链
        add_windows_root_certs(ctx);
#endif

        // 这个方法可以显示添加某个pem证书文件
        //ctx->load_verify_file("");
    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
    }
    return ctx;
}

运行成功。

TODO:open ssl 静态库没有debug版本,使用MT运行库,为什么可以和使用MTD运行库的examples一起编译?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/506680.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

KMP字符串匹配算法

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 目录 一.KMP 二.next数组&#xff08;前缀表&#xff09; 三.具体实现模板 四.题解 先来看一个问题 28. 找出字符串中第一个匹配项的下标 - 力扣&#xff08;LeetCode&#xff09; 对于这个问题&#xff0c;一般暴力做法…

三、Java的流程控制

1、Java的顺序流程控制 程序由一系列语句组成。 Java虽然是一种面向对象的计算机语言,但是在一个局部,例如方法体内,快语句内仍然需要面向过程的程序设计和方法。 作为面向过程程序设计精华的结构化程序设计思想,仍然是面向对象程序设计方法的基石。 1)表达式语句 由运…

浪潮分布式存储AS13000G6-M36、NF5466M6硬盘背板改扩配参考

AS13000G6分布式存储机型描述 浪潮分布式存储AS13000G6-M36机型&#xff0c;实际就是NF5466M6加上分布式存储软件的一体机产品&#xff0c;而NF5468M6也就是NF5280M6的主板加4U机箱结构。 该机器最大的特点是在4U空间内可以配置36块3.5寸大盘&#xff0c;硬盘背板为3.5*12&…

B82793S0513N201 共模扼流圈滤波器电感 51uH 800mA

B82793S0513N201是一款由TDK(东电化)公司生产的数据线扼流圈&#xff0c;用于电信领域的xDSL变压器。 制造商: TDK 产品品种: 共模扼流圈/滤波器 RoHS: 详细信息 系列: B82793S 安装风格: PCB Mount 端接类型: SMD/SMT 通道数量: 1 Channel 电感: 51 uH 容差: 30 % 最大直流电…

护眼台灯什么品牌好?台灯目前口碑最好的护眼灯推荐

随着生活水平的提供&#xff0c;越来越多的人重视起自身健康问题&#xff0c;尤其是视力健康&#xff0c;因此都会选择一款好的护眼台灯。不过市面上的护眼台灯款式多得人数不清&#xff0c;其中还包括了很多劣质产品。 这类台灯往往采用劣质LED灯珠&#xff0c;这种灯珠对人体…

【5G 接口协议】CU与DU之间的F1协议介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

如何使用 Python 本地客户端操作读写云服务器 Redis 缓存数据库详细教程(更新中)

Redis 基本概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的使用 ANSI C 语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库&#xff0c;并提供多种语言的 API。它通常被称为数据结构服务器&#xff0c;因为值&#xff08;value…

【Leetcode】2810. 故障键盘

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 你的笔记本键盘存在故障&#xff0c;每当你在上面输入字符 ′ i ′ i ′i′ 时&#xff0c;它会反转你所写的字符串。而输入其他字符则可以正常工作。 给你一个下标从 0 0 0 开始…

.sdf和.msp文件读取

前言 .sdf和.msp文件都可以用来存储分子信息&#xff0c;.sdf文件可以用rdkit读取&#xff0c;.msp文件就只能当成文本文档读取了。 读取 rdkit安装 pip install rdkit .sdf读取 from rdkit import Chemsuppl_h Chem.SDMolSupplier(../data/HMDB/f_hmdb.sdf) # 得到一个迭…

【字节跳动笔试题汇总】 2024-03-31-字节跳动春招笔试题-三语言题解(CPP/Python/Java)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新字节跳动近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&…

基于Python的口罩佩戴识别的设计与实现(UI界面+MySQL数据库+YOLOv5+训练数据集+开题报告+中期检查+论文)

本文旨在基于Python开发一种口罩佩戴识别系统&#xff0c;通过深度学习技术实现对口罩佩戴情况的准确检测。采用了YOLOv5系列目标检测算法作为基础模型&#xff0c;并结合迁移学习进行训练和优化。同时&#xff0c;为了提供更好的用户体验&#xff0c;本系统还设计了用户登录注…

“315晚会”中的“网络水军”是什么?

水军一词&#xff0c;源自网络用语&#xff0c;通常指的是一群在网络上被雇佣来进行特定活动的人群。他们的主要任务通常是在各种社交媒体平台、论坛或者评论区发表大量的帖子、评论或者回复&#xff0c;以此来达到某种特定的目的。这些目的可能包括提升某个产品、服务或者个人…

【机器学习300问】58、什么是词袋模型和N-gram模型?

词袋模型&#xff08;Bag of Words, BoW&#xff09;和N-gram模型主要用于早期的自然语言处理任务&#xff0c;上文中我介绍了机器是如何读懂文本的四个阶段&#xff0c;这篇文章带大家来看看在不同阶段中会用到的两个模型——词袋模型和N-gram模型。如果没有读过我之前的文章&…

纯小白蓝桥杯备赛笔记--DAY9(搜索)

文章目录 三道例题学会DFS剪枝什么是剪枝数字王国之军训排队--2942特殊的三角形--3008特殊的多边形--3075 DFS基础回溯简介回溯法模版例题N皇后--1508小朋友崇拜圈--182全球变暖--178 记忆化搜索简介斐波那契数列混境之地5-3820地宫取宝-216 三道例题学会DFS剪枝 什么是剪枝 …

云计算迎变局:阿里云、腾讯云“各有千秋”

毋庸置疑&#xff0c;无论在什么时候什么行业&#xff0c;低价策略都是一柄利器。比如&#xff0c;在电商行业&#xff0c;除了拼多多将低价策略贯彻到底之外&#xff0c;淘宝、京东也将性价比作为发力重点&#xff0c;并通过补贴、秒杀等方式&#xff0c;再度强调自身的“价格…

Pygame基础8-碰撞

Collisions 在Pygame中&#xff0c;我们使用矩形来移动物体&#xff0c;并且用矩形检测碰撞。 colliderect检测两个矩形是否碰撞&#xff0c;但是没法确定碰撞的方向。 Rect1.colliderect(Rect2) # collision -> return Ture # else -> return Falsecollidepoint可以…

数据结构——遍历二叉树和线索二叉树,树和森林

目录 1.遍历的算法实现 1.先序遍历 代码示例&#xff1a; 2.中序遍历 代码示例&#xff1a; 3.后序遍历 代码示例&#xff1a; 4.遍历算法的分析 2.遍历二叉树的非递归算法 1.中序遍历非递归算法 代码示例&#xff1a; 3.二叉树的层次遍历 代码示例&#xff1a; 4.二…

C#/.NET/.NET Core优秀项目和框架2024年3月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;每周至少会推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学…

BUUCTF [安洵杯 2019]吹着贝斯扫二维码 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件解压&#xff0c;得到很多没有后缀的文件和一个ZIP压缩包。 解题思路&#xff1a; 1、首先&#xff0c;查看ZIP压缩包&#xff0c;发现有密码&#xf…

GreatSQL 优化技巧:将 MINUS 改写为标量子查询

GreatSQL 优化技巧&#xff1a;将 MINUS 改写为标量子查询 前言 minus 指令运用在两个 SQL 语句上&#xff0c;取两个语句查询结果集的差集。它先找出第一个 SQL 所产生的结果&#xff0c;然后看这些结果有没有在第二个 SQL 的结果中&#xff0c;如果在&#xff0c;那这些数据…