C++的httplib库源码阅读笔记(2)
本文解析了cpp-httplib库的头文件设计,重点介绍了非Windows系统下的网络编程头文件(如arpa/inet.h、netdb.h等)及其功能,包括字节序转换、网络接口操作、DNS解析等。同时说明了跨平台处理机制,如针对不同操作系统(Windows/macOS)和加密库(OpenSSL/mbedTLS)的条件编译,以及压缩功能(zlib/Brotli)的可选支持。文章展示了该库如何通过灵活
一 .前言
紧接上文,我们继续来阅读httplib库源码。
二 .非Windows操作系统头文件
#include <arpa/inet.h>
主机序列与网络的大端字节序列的转换函数在这个头文件中。分别是以下四个:
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
h表示主机,n表示网络,l表示long,一般就是4字节ipv4地址,s表示short,一般就是端口。
#if !defined(_AIX) && !defined(__MVS__)
#include <ifaddrs.h>
#endif
_AIX和__MVS__是IBM的两种操作系统的预定义宏。
#include <ifaddrs.h> 提供一套标准化接口,让程序能便捷获取本机所有网络接口的详细信息(比如网卡名、IP 地址、地址类型、接口状态等),其中有两个核心函数:
-
getifaddrs(struct ifaddrs **ifap):获取所有网络接口信息,结果以链表形式存入ifap; -
freeifaddrs(struct ifaddrs *ifa):释放getifaddrs申请的内存(必须调用,避免内存泄漏)。
这个头文件中函数的具体作用在源码中用到的时候再详细说明。
#include <net/if.h>
<net/if.h> 是 POSIX 标准 的网络编程头文件(类 UNIX 系统通用,包括 Linux、macOS、BSD 等),核心作用是:定义与网络接口(网卡) 相关的常量、结构体和辅助函数,是操作网卡基础属性的核心头文件,常与 ioctl() 系统调用、<ifaddrs.h> 配合使用。
#include <netdb.h>
提供一套标准化接口,实现域名 / 服务名与 IP 地址 / 端口号之间的转换(即 DNS 解析、服务名解析),是网络编程中 “地址解析” 的核心头文件。
#include <netinet/in.h>
定义与 Internet 协议(TCP/IP) 相关的核心数据结构、常量和字节序转换函数,是编写 TCP/UDP 网络程序的基础。
简单来说,只要涉及 IPv4/IPv6 地址、端口号、TCP/UDP 套接字编程,几乎都离不开这个头文件。在Linux环境进行socket编程时,这个头文件通常会被间接包含。
#include <resolv.h>
这是遵循 BSD 标准 的 DNS 编程头文件(Linux/macOS/BSD 通用),核心作用是:提供直接操作 DNS 解析器(resolver) 的底层接口,包括配置 DNS 服务器、自定义 DNS 查询(A/AAAA/MX 记录等)、设置解析超时等,是比 <netdb.h> 更底层的 DNS 编程工具。
简单来说,<netdb.h> 是 “封装好的 DNS 解析工具”(如 getaddrinfo),而 <resolv.h> 是 “手动操控 DNS 解析器的工具箱”,能实现更灵活的 DNS 操作。
#include <csignal>
C++ 封装的信号处理头文件。
#include <netinet/tcp.h>
定义 TCP 协议相关选项(如 TCP_NODELAY),配置 TCP 套接字特性。在Linux平台进行socket编程时一般会间接包含。
#include <poll.h>
提供 poll () 函数,实现 I/O 多路复用。
#include <pthread.h>
定义线程创建 / 同步。
#include <sys/mman.h>
<sys/mman.h> 遵循 POSIX 标准,核心作用是:提供一套接口,将文件 / 设备的内容直接映射到进程的虚拟内存空间,或创建匿名内存区域(用于进程间共享内存)。简单来说,它让程序可以像操作普通内存一样操作文件 / 设备,无需调用 read()/write() 等传统 I/O 函数,大幅提升 I/O 效率。
#include <sys/socket.h>
核心套接字编程头文件,定义 socket/bind/listen/accept 等基础网络函数。
#include <sys/un.h>
定义 Unix 域套接字(AF_UNIX)相关结构体(sockaddr_un)。
#include <unistd.h>
Unix 标准头文件,提供 read/write/close/fork 等系统调用。
using socket_t = int;
#ifndef INVALID_SOCKET
#define INVALID_SOCKET (-1)
#endif
#endif //_WIN32
跨平台统一和无效socket的宏定义。
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
苹果系统下精准区分 macOS/iOS/ 模拟器等编译目标。
三.全操作系统公共头文件
#include <algorithm>
#include <array>
#include <atomic> // 提供原子类型和原子操作函数
#include <cassert>
#include <cctype>
#include <chrono> // C++ 标准库中专门处理时间和日期的头文件
#include <climits>
#include <condition_variable> // 实现多线程间的条件同步,让线程按需等待 / 唤醒,避免忙等
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <exception>
#include <fcntl.h> // 操作文件描述符的 “总入口”
#include <functional>
#include <iomanip> // 控制 C++ 输入输出流的格式,实现精细化的文本 / 数字打印
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <random>
#include <regex> // 专门处理正则表达式的头文件
#include <set>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <system_error>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <utility> // 提供 C++ 通用工具函数 / 模板
上面这部分头文件在日常开发中会经常用到,所以只做注释说明。
#if defined(CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO) || \
defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
#if TARGET_OS_MAC
#include <CFNetwork/CFHost.h> // 提供 macOS/iOS 下的网络地址解析
#include <CoreFoundation/CoreFoundation.h> // 苹果核心基础框架,提供内存管理、字符串 / 数组等基础类型
#endif
#endif // CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO or
// CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
#ifdef _WIN32
#include <wincrypt.h> // Windows 系统下 CryptoAPI 的核心头文件,提供加密 / 哈希 / 证书相关接口;
// these are defined in wincrypt.h and it breaks compilation if BoringSSL is
// used
#undef X509_NAME
#undef X509_CERT_PAIR
#undef X509_EXTENSIONS
#undef PKCS7_SIGNER_INFO
#ifdef _MSC_VER
#pragma comment(lib, "crypt32.lib")
#endif
#endif // _WIN32
#if defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
#if TARGET_OS_MAC
#include <Security/Security.h> // 主打钥匙串管理、证书操作、加密安全
#endif
#endif // CPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO
#include <openssl/err.h> // OpenSSL 错误处理核心头文件
#include <openssl/evp.h> // OpenSSL 高级加密接口头文件,封装对称 / 非对称加密、哈希、签名等算法
#include <openssl/ssl.h> // OpenSSL SSL/TLS 协议核心头文件,定义 SSL 上下文、连接、证书验证等函数
#include <openssl/x509v3.h> // X.509 v3 证书扩展处理头文件,解析 / 生成证书扩展字段
#if defined(_WIN32) && defined(OPENSSL_USE_APPLINK)
#include <openssl/applink.c> // 解决 Windows 平台下 OpenSSL 与 C/C++ 运行时库的链接冲突
#endif
#include <iostream>
#include <sstream>
#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
#if OPENSSL_VERSION_NUMBER < 0x1010107f
#error Please use OpenSSL or a current version of BoringSSL
#endif
#define SSL_get1_peer_certificate SSL_get_peer_certificate
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
#error Sorry, OpenSSL versions prior to 3.0.0 are not supported
#endif
#endif // CPPHTTPLIB_OPENSSL_SUPPORT
// cpp-httplib 库针对 mbedTLS 加密库的跨平台条件编译逻辑
#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/error.h>
#include <mbedtls/md5.h>
#include <mbedtls/net_sockets.h>
#include <mbedtls/oid.h>
#include <mbedtls/pk.h>
#include <mbedtls/sha1.h>
#include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
#include <mbedtls/ssl.h>
#include <mbedtls/x509_crt.h>
#ifdef _WIN32
#include <wincrypt.h>
#ifdef _MSC_VER
#pragma comment(lib, "crypt32.lib")
#endif
#endif // _WIN32
#if defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
#if TARGET_OS_MAC
#include <Security/Security.h>
#endif
#endif // CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN
// Mbed TLS 3.x API compatibility
#if MBEDTLS_VERSION_MAJOR >= 3
#define CPPHTTPLIB_MBEDTLS_V3
#endif
#endif // CPPHTTPLIB_MBEDTLS_SUPPORT
// Define CPPHTTPLIB_SSL_ENABLED if any SSL backend is available
// This simplifies conditional compilation when adding new backends (e.g.,
// wolfSSL)
#if defined(CPPHTTPLIB_OPENSSL_SUPPORT) || defined(CPPHTTPLIB_MBEDTLS_SUPPORT)
#define CPPHTTPLIB_SSL_ENABLED
#endif
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
#include <zlib.h> // 提供轻量级、跨平台的 DEFLATE 算法压缩 / 解压缩接口
#endif
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
#include <brotli/decode.h> // 实现 Brotli 高压缩率算法的编码 / 解码,是 zlib/gzip 的升级版
#include <brotli/encode.h>
#endif
#ifdef CPPHTTPLIB_ZSTD_SUPPORT
#include <zstd.h> // 实现 Zstd 算法的高性能压缩 / 解压缩,兼顾压缩率和速度
#endif
按宏开关按需加载 SSL(OpenSSL/mbedTLS)、压缩(zlib/Brotli/Zstd)功能的头文件;适配 Windows/macOS 等系统的平台差异,解决编译冲突;校验加密库版本,定义兼容宏,保证不同环境下代码的可编译性。
这段代码是 cpp-httplib 实现 “跨平台、可插拔式功能扩展” 的基础,让库能根据用户的编译选项,适配不同系统和第三方库(加密 / 压缩)。需要用到这部分代码中的某些头文件时,我们只需要定义相应的宏。
四.总结
httplib的头文件部分阅读完毕,httplib库源码具体用到头文件里的东西时再做具体讲解。
更多推荐



所有评论(0)