【C++进阶】详解C++开源网络传输库libcurl的编译过程
目录
1、引言
2、直接编译libcurl工程,提示找不到ssh.h
3、下载并编译libssh2开源代码,部署到libcurl目录中
4、获取openssl开源库的头文件和库文件,部署到libcurl目录中
5、将编译好的libcurl拿到测试项目中测试
6、使用CMake工具手动生成VS工程文件,可以轻易地编译出libcurl库
7、总结
libcurl是一个免费开源的网络传输库(the multiprotocol file transfer library),支持ftp、ftps、http、https、telnet、ldap、pop3、smtp、rtmp、rtsp、smb等多种协议。libcurl中封装了支持这些协议的网络通信模块,支持跨平台,支持Windows,Unix,Linux等多个操作系统。libcurl提供了一套统一样式的API接口,我们不用关注各种协议下网络通信的实现细节,只需要调用这些API就能轻松地实现基于这些协议的数据通信。本文我们来详细讲述一下如何编译开源的libcurl库。
1、引言
之前开发的一个工具软件中有个发送告警邮件的功能,最开始试图通过socket套接字去实现邮件的发送,先是和邮件服务器建立连接,然后进行SMTP邮件的协商,协商完成后将邮件发送出去。结果联调测试时遇到了一堆问题,各种网络异常没有得到很好的处理,导致发送邮件功能根本没法使用。
后来想到了libcurl开源库,该库中封装了smtp邮件协议的所有功能,从连接到协议协商,再到邮件数据的发送,提供一套完整、可靠、稳定的邮件发送机制。于是想去下载libcurl的开源代码,手动将库编译出来,然后再拿到工具软件中使用,同时也正好熟悉一下libcurl开源库的编译过程。
关于发送告警邮件的项目,可以查看之前写的文章:(下列文章中提供免费C++源码项目下载)
IPC摄像头在线状态ping检测与告警邮件发送项目总结(提供源码下载)https://blog.csdn.net/chenlycly/article/details/120690137
2、直接编译libcurl工程,提示找不到ssh.h
到libcurl的官网上下载libcurl源码。我下载的是2022年5月11日发布的curl 7.83.1版本。解压后,打开curl-7.83.1\projects\Windows目录,该目录中保存了支持Widnows平台上的Visual Studio编译的工程文件,提供了对多个Visual Studio版本的支持:
此处我是用Visual Studio 2010编译的,所以选择VC10目录。打开VC10目录,双击curl-all.sln解决方案文件启动VS2010打开解决方案,该解决方案中包含了curl和libcurl两个工程,libcurl是动态库工程,我们编译该工程就可以了。
在libcurl源代码根路径中提供了CMakeLists.txt文件,如果开源库中不提供支持Visual Studio编译的工程文件,我们可以对CMakeLists.txt文件使用CMAKE工具,生成指定版本的Visual Studio工程文件。注意在使用CMake工具时,开源代码的所在路径必须是全英文的,不能包含中文,否则CMake工具会将路径中的中文字符识别位乱码,导致生成Visual Studio工程文件失败。
启动对libcurl工程的编译后,就报错了,如下所示:
1>------ 已启动生成: 项目: libcurl, 配置: DLL Release - DLL OpenSSL Win32 ------
1>生成启动时间为 2022/5/17 16:32:39。
1>InitializeBuildStatus:
1> 正在创建“..\..\..\..\build\Win32\VC10\DLL Release - DLL OpenSSL\lib\libcurl.unsuccessfulbuild”,因为已指定“AlwaysCreate”。
1>ClCompile:
1> x509asn1.c
1> wolfssl.c
1> vtls.c
1>e:\开源库集合\curl-7.83.1\lib\vssh/ssh.h(28): fatal error C1083: 无法打开包括文件:“libssh2.h”: No such file or directory
1> sectransp.c
1>e:\开源库集合\curl-7.83.1\lib\vssh/ssh.h(28): fatal error C1083: 无法打开包括文件:“libssh2.h”: No such file or directory
1> schannel_verify.c
提示找不到ssh.h。从解决方案配置中看到了libssh2库的身影,应该是当前的libcurl库使用了开源的libssh2库,于是去下载libssh2开源库代码,一是拿到libssh2库的头文件,二是将libssh2库的库文件编译出来,libcurl链接时肯定要用到libssh2库的。
3、下载并编译libssh2开源代码,部署到libcurl目录中
SSH为Secure Shell的缩写,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH1由于存在安全漏洞,所以产生了更为安全的SSH2,开源libssh2库实现了SSH2协议。
到libssh2官网上下载libssh2源码,解压后打开根路径,发现根路径下有个win32文件夹,点进去后看到Visual Studio相关的工程文件,如下所示:
工程文件是VC++6.0版本的,直接将工程文件拖到VS2010中,将工程文件升级到VS2010版本,然后发起编译,很快就编译完成了。
查看了一下libssh2工程的属性,发现该工程编译出来的是静态库,不是动态库,如下所示:
因为此处生成的是libssh2静态库,所以我们在libcurl的解决方案配置中选择“DLL Release - DLL OpenSSL”工程选项:
这个选项是使用libssh2静态库的。而DLL Release - DLL OpenSSL - DLL LibSSH2选项中则使用的是libssh2动态库,所以我们要使用前者。
于是将libssh2库目录中的include头文件以及编译出来的静态库拷贝到libcurl的工程目录curl-7.83.1中。我们在curl-7.83.1目录中创建一个名叫libssh2文件夹,然后在该文件夹中创建一个用来存放头文件的include文件夹和一个用来存放libssh2静态库的lib文件夹,如下:
于是我们到libcurl的工程属性中修改一下配置,首先修改引用libssh2\include下头文件的路径(包含头文件):
然后修改引用libssh2\lib目录下的libssh2.lib文件的路径(链接时引入的.lib文件):
于是继续编译libcurl工程,结果又提示找不到ssl.h头文件:
1>------ 已启动生成: 项目: libcurl, 配置: DLL Release - DLL OpenSSL Win32 ------
1>生成启动时间为 2022/5/17 17:01:17。
1>InitializeBuildStatus:
1> 正在对“..\..\..\..\build\Win32\VC10\DLL Release - DLL OpenSSL\lib\libcurl.unsuccessfulbuild”执行 Touch 任务。
1>ClCompile:
1> x509asn1.c
1> wolfssl.c
1> vtls.c
1> sectransp.c
1> schannel_verify.c
1> schannel.c
1> rustls.c
1> openssl.c
1>..\..\..\..\lib\vtls\openssl.c(63): fatal error C1083: 无法打开包括文件:“openssl/ssl.h”: No such file or directory
1> nss.c
1> mbedtls_threadlock.c
应该是和libssh2库一样,也需要获取openssl开源库的头文件和库文件。
4、获取openssl开源库的头文件和库文件,部署到libcurl目录中
到curl-7.83.1目录中去搜索,也找不到ssl.h文件。那应该是要去下载openssl开源库的源码并编译。到openssl官网上将源码下载下来,解压后在根路径中没有找到Windows平台编译专用的Visual Studio的工程文件,而libcurl和libssh2源码中是有专用的Visual Studio工程文件的。如果要手动编译openssl,则需要安装perl工具,然后通过perl去执行代码的编译,这个过程略显复杂。
我们可以到第三方网站上去下载别人已经编译好的openssl库,比如:
Win32/Win64 OpenSSL Installer for Windows - Shining Light Productionshttp://slproweb.com/products/Win32OpenSSL.html打开页面后,将页面向下拉动找到下载链接,我们的软件是32位的,所以选择32位版本的openssl即可。但下载链接比较多,我们只需要选择Win32 OpenSSL v3.0.3 Light版本即可,点击MSI按钮,下载MSI安装包:
然后执行该MSI安装包,这样就能把openssl头文件和库文件释放到目标路径中。然后打开安装目录查看安装的内容,从include路径中取出所有头文件,从lib路径中取出用于链接的.lib库,从bin路径中取出libssl-3.dll及其依赖的库。
lib路径中的文件比较多:
我们只需要取出libcurl链接时要用的libssl.lib库文件即可。
bin路径下的文件也比较多,除了要拿openssl库的主文件libssl-3.dll,还要取出哪些libssl-3.dll库依赖的dll文件呢?其实很简单,我们只需要使用Dependency Walker工具打开libssl-3.dll文件,看看libssl-3.dll依赖哪些dll库,如下所示:
除去libssl-3.dll依赖的一些系统库之外,我们看到了libssl-3.dll依赖了libcrypto-3.dll库,
在这个地方有个细节需要注意一下,Dependency Walker工具在Win10系统中打开dll很慢,等待的时间会比较长,估计得等1分钟左右,使用时要去耐心等待一会,等待Dependency Walker打开dll库完成,估计是因为Dependency Walker对Win10的兼容性不好导致打开dll文件很慢的。
和libssh2库处理类似,我们也在curl-7.83.1目录的根目录中创建一个openssl目录,在该目录再创建一个存放openssl头文件夹include,再创建一个存放.lib和.dll文件的lib路径。然后从之前Win32 OpenSSL v3.0.3 Light的安装目录中将相关文件拷贝过去。
接下来,我们到libcurl的工程属性中修改一下配置,首先修改引用openssl\include下的头文件路径(包含头文件):
然后修改引用openssl\lib目录下的libssl.lib文件的路径(链接时引入的.lib文件):
于是再编译libcurl工程,结果还是报找不到ssl.h头文件的错误:
1>------ 已启动生成: 项目: libcurl, 配置: DLL Release - DLL OpenSSL Win32 ------
1>生成启动时间为 2022/5/17 17:01:17。
1>InitializeBuildStatus:
1> 正在对“..\..\..\..\build\Win32\VC10\DLL Release - DLL OpenSSL\lib\libcurl.unsuccessfulbuild”执行 Touch 任务。
1>ClCompile:
1> x509asn1.c
1> wolfssl.c
1> vtls.c
1> sectransp.c
1> schannel_verify.c
1> schannel.c
1> rustls.c
1> openssl.c
1>..\..\..\..\lib\vtls\openssl.c(63): fatal error C1083: 无法打开包括文件:“openssl/ssl.h”: No such file or directory
1> nss.c
1> mbedtls_threadlock.c
后来查阅代码得知,代码中引用ssl.h头文件的地方,都加上了openssl相对路径,如下:
为了解决这个问题,我们再在include中添加一个openssl子文件夹,将所有openssl的头文件都搞到这个openssl子文件夹中存放,然后libcurl就能编译通过了。
5、将编译好的libcurl拿到测试项目中测试
将编译好的release版本的libcurl库及其依赖的几个库,拷贝到之前编写的包含发送邮件的程序中编译,运行测试程序,打开邮箱参数设置窗口,如下所示:
在邮箱参数设置窗口中填写好163邮箱SMTP服务器地址及端口、发送邮件地址和接收邮件通知的接收邮件地址,点击“发送接收邮件”按钮,发送测试邮件。经验证,是可以将测试邮件发出去的:
目标邮箱中也是能收到邮件的,邮件内容也是正确的。
至于如何开通发送邮件中的SMTP服务,可以参见之前写的这篇文章:
VC++调用libcurl开源库实现发送邮件的功能(附源码)https://blog.csdn.net/chenlycly/article/details/121318616
6、使用CMake工具手动生成VS工程文件,可以轻易地编译出libcurl库
libcurl开源代码的根目录中就有个CMakeLists.txt文件,该文件中配置了生成Windows平台上的Visual Studio工程文件的相关内容,于是使用CMake工具尝试自行生成VS工程文件。
CMake 是一个跨平台的开源构建系统,通过读取放置在每个源码根目录中的配置文件CMakeLists.txt中的内容,生成指定平台的标准构建文件,比如为 Unix 平台生成makefiles文件(用GCC编译),为 Windows平台的MSVC(Microsoft Visual Studio C++)生成 projects/workspaces(用Visual Studio编译)或makefile文件(用nmake编译)。
打开CMake工具后,先设置libcurl源码的根路径,然后再设置生成的Visual Studio工程文件的目录:
然后点击Generate按钮,弹出选择哪种解决方案:
此处我们需要使用VS2010,所生成VC++工程文件的时间比较长,大概需要等待几分钟时间,生成完成后,我们打开对应的目录,如下所示:
打开后编译libcurl工程即可,编译速度很快。根据编译时打印的信息得知,该种方式下使用的是wolfssl,没有使用openssl,libcurl的目录中也找不到openssl的头文件,所以通过CMake工具生成的VS工程编译时不需要libssh2和openssl开源库了,如下:
根据编译输出的路径,可以到对应的路径中找到生成的libcurl库文件:libcurl_imp.lib和libcurl.dll。
相比于上面那种编译libssh2开源库及获取openssl库的方式,这种方式要简单的多。将libcurl_imp.lib和libcurl.dll拿到测试工具的工程中测试,也是能正常发送邮件的。
7、总结
上面使用了两个途径去编译libcurl库。一种是使用libcurl开源库自带的VS工程去编译,但要先去编译libssh2开源库,然后去获取openssl开源库的头文件及库文件,最后再来编译libcurl工程。另一种方式是使用CMake工具,输入CMakeLists.txt,即可自动生成VC的工程,可以直接编译出libcurl库,不需要再去编译libssh2和openssl库。经测试,这两种方式编译出来的库都是可用的,都能将测试邮件发送出去。
【C++进阶】详解C++开源网络传输库libcurl的编译过程相关推荐
- 基于linux-2.6.34内核编译详解,Linux 2.6、4.3内核编译过程的感受与总结
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 之前编译过2.4.10版本的内核,很好编译,中间曾经漏下了SCSI low-level drivers下的BusLogi ...
- 2接口详解_TS入门笔记2——TS接口进阶详解
TS入门笔记--TS接口进阶详解 一.为什么需要接口? let obj:object; // 定义了一个只能保存对象的变量 // obj = 1; // obj = "123"; ...
- ubuntu下sed命令详解 - Dicky - 开源中国社区
ubuntu下sed命令详解 - Dicky - 开源中国社区 ubuntu下sed命令详解 - Dicky - 开源中国社区 ubuntu下sed命令详解 7人收藏此文章, 我要收藏 发表于 ...
- 【React】 详解下一代开源混合应用框架Reapp
详解下一代开源混合应用框架Reapp reapp官网 转载于:https://www.cnblogs.com/dongdong230/p/4314978.html
- 深度学习网络模型——RepVGG网络详解、RepVGG网络训练花分类数据集整体项目实现
深度学习网络模型--RepVGG网络详解.RepVGG网络训练花分类数据集整体项目实现 0 前言 1 RepVGG Block详解 2 结构重参数化 2.1 融合Conv2d和BN 2.2 Conv2 ...
- linux上 arm开发环境搭建,详解 LINUX下QT For ARM开发环境搭建过程
LINUX下QT For ARM开发环境搭建过程是本文介绍的内容,不多说,先来看内容.在PC上,我们需要得到两个版本的Qt,分别是:Qt-4.5.2和QtEmbedded-4.5.2-arm.前者包括 ...
- winform访问被拒绝_详解C#对路径...的访问被拒绝解决过程
用C#想写一个直接将数据库查询得到的datatable,直接导出为csv格式的文件,拷贝到导出的操作类后,一直catch到的错误提示是对路径的泛微被拒绝,一直排查原因,发现原来:FileStream( ...
- Redis基础与高可用集群架构进阶详解
一.NoSQL简介 1.问题引入 每年到了过年期间,大家都会自觉自发的组织一场活动,叫做春运!以前我们买票都是到火车站排队,后来呢,有了 12306,有了它以后就更方便了,我们可以在网上买票,但是带来 ...
- 【笔记】IP地址详解、Linux网络及常用命令
IP地址 IP地址基本概念 IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址.IP地址在网络层将不同的物理网络地址统一到了全球唯一的IP地址上(屏蔽 ...
最新文章
- 干货!机器学习中,如何优化数据性能
- is this mysql server_Mysql:is not allowed to connect to this MySQL server
- JavaScript的表单事件
- Codeforces Round #635 (Div. 2) D. Xenia and Colorful Gems 暴力 + 二分
- 休眠:在sqlRestriction上使用联接表别名
- WinPcap笔记(3):获取已安装设备的详细信息
- xss跨站脚本攻击_网络安全xss跨站脚本攻击原理
- javascript : instanceof,typeof,constructor
- vue中实现国际化--语言切换(转载)
- 《ActionScript 3.0基础教程》——2.2 显示队列概述
- 《我和PIC单片机:基于PIC18》——2.2 MPLAB IDE集成开发环境
- 服务器数据恢复建议_raid磁盘阵列OFFLINE后的应急处理方案
- 获取input输入值和获取form表单中的组件输入值区别
- android icon背景透明,Android 图标去白色背景换成透明 用Photoshop实现
- PC时代的20位英雄
- NSArray进行汉字排序
- Linux应用程序动态更改用户ID
- IDEA中maven使用tomcat插件,tomcat并没有启动,无tomcat日志信息
- 浅析智能网联产业发展与变化趋势
- 解决“System.Data.OracleClient 需要 Oracle 客户端软件 version 8.1.7 或更高版本”的问题