curl完整文档

curl 与 libcurl 概述

本文档整理自 curl/curl 官方文档与社区资料,便于本地查阅与二次整理。

目录

  1. 概述
  2. 快速开始
  3. 构建与安装
  4. 基本用法示例
  5. 命令行选项参考
  6. 最新更新
  7. 问题与反馈
  8. 关于贡献者
  9. 架构概述
  10. [libcurl API 设计](#libcurl API 设计)
  11. 简易句柄生命周期
  12. 简易选项配置
  13. 简易执行机制
  14. 多句柄架构
  15. 并发传输
  16. 基于事件的操作
  17. [HTTP 协议实现](#HTTP 协议实现)
  18. [HTTP/2 和 HTTP/3 支持](#HTTP/2 和 HTTP/3 支持)
  19. [TLS 后端选择](#TLS 后端选择)
  20. [TLS 会话管理](#TLS 会话管理)
  21. 证书处理
  22. 连接池与复用
  23. 传输层架构
  24. [FTP 和 SFTP 实现](#FTP 和 SFTP 实现)
  25. [SMTP 和 POP3 处理](#SMTP 和 POP3 处理)
  26. [WebSocket 支持](#WebSocket 支持)
  27. 身份认证机制
  28. 代理支持与隧道
  29. 连接过滤系统
  30. [URL 解析与操作](#URL 解析与操作)
  31. [Unix 域套接字](#Unix 域套接字)
  32. [Windows 特有功能](#Windows 特有功能)
  33. 跨平台可移植性
  34. 延伸阅读与参考链接

概述

欢迎来到 curl,这是世界上最广泛使用的命令行工具和库,用于通过 URL 传输数据。本概述介绍 curl 是什么、其结构以及使其成为互联网通信基石的关键组件。

什么是 curl?

curl 是一个双组件项目 :由命令行工具 和名为 libcurl 的传输库组成。命令行工具提供简单而强大的数据传输接口,libcurl 提供完整 API,用于将传输能力集成到自己的应用中。curl 支持多种协议,包括 DICT、FILE、FTP、FTPS、GOPHER、GOPHERS、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、MQTT、POP3、POP3S、RTMP、RTMPS、RTSP、SCP、SFTP、SMB、SMBS、SMTP、SMTPS、TELNET、TFTP、WS 和 WSS。项目开源,按类 MIT 许可证分发,可免费用于个人与商业用途。

项目结构

  • src/ :curl 命令行工具实现,主入口在 tool_main.c,负责参数解析、初始化与传输调用;模块化设计便于维护与扩展。
  • lib/ :libcurl 核心实现,包含大量源文件,涵盖网络与协议。核心包括 easy 接口easy.c,阻塞式简单传输)与 multi 接口multi.c,并发非阻塞传输);协议处理、连接管理、TLS 与工具函数分层协作。
  • include/curl/ :公共 API 头文件(如 curl.heasy.hmulti.h),是与应用之间的稳定契约。
  • docs/:用法、内部结构、功能与贡献指南等文档,是理解功能与开发实践的主要来源。

架构概述

Easy 接口 :用 curl_easy_init() 创建句柄,curl_easy_setopt() 设置选项,curl_easy_perform() 执行传输;调用阻塞直到传输结束,适合同步、简单场景。

Multi 接口 :用 curl_multi_init() 创建 multi 句柄,curl_multi_add_handle() 添加多个 easy 句柄,curl_multi_wait() / curl_multi_perform() 等监视活动;支持并发、非阻塞与事件驱动,适合高性能、多连接场景。

核心功能

类别 能力 描述
HTTP/HTTPS HTTP/0.9--1.1、HTTP/2、HTTP/3 完整 HTTP 支持,多路复用、服务器推送与安全特性
身份验证 Basic、Digest、NTLM、Negotiate、OAuth2 服务器与代理认证
TLS OpenSSL、GnuTLS、mbedTLS、WolfSSL、Schannel 等 多后端、会话恢复与证书处理
连接管理 持久连接、连接池、keepalive TCP Fast Open、Happy Eyeballs 等
传输控制 速率限制、超时、恢复、范围请求 细粒度控制
数据处理 分块、压缩、cookies、headers brotli、zstd、gzip 等
代理 HTTP、HTTPS、SOCKS4、SOCKS5 隧道、认证与链式代理

协议支持不限于 HTTP:FTP(主动/被动、目录列表、恢复)、邮件(SMTP、POP3、IMAP 及安全变体)、SSH(SCP、SFTP)、MQTT 等均在 lib 中分文件实现。安全方面支持 TLS False Start、版本控制、会话恢复、证书固定与双向认证;证书可来自 CA 包或系统存储。连接过滤系统(如 cf-socket、cf-https-connect)提供可组合的协议栈,便于集成代理、TLS 与 Happy Eyeballs。

入门指南与后续步骤

初学者建议从 easy 接口 入手:创建 easy 句柄、设置 URL 与数据回调、调用 curl_easy_perform()。需要并发时再过渡到 multi 接口 。可参考官方 curl 网站、man 手册与《everything curl》书籍;代码库中 docs/examples/tests/ 也提供丰富示例。后续可阅读快速开始、构建与安装、基本用法示例与架构概述等章节,从基本用法逐步深入到实现细节。


快速开始

本指南帮助快速入门 curl 与 libcurl(命令行或库集成)。curl 是使用 URL 在服务器间传输数据的命令行工具,支持 HTTP、HTTPS、FTP、SFTP、SMTP 等众多协议;libcurl 是底层可移植库,被大量应用使用。

快速安装

命令行 curl :多数 Linux 已预装。macOS:brew install curl。Ubuntu/Debian:sudo apt-get install curl。Windows(Chocolatey):choco install curl

从源码构建 libcurl./configure --with-opensslmakemake test(可选)→ make install。若从 git 构建需先运行 ./buildconf 生成 configure。

第一个 curl 命令

bash 复制代码
curl https://www.example.com/
# 保存到指定文件
curl -o webpage.html https://www.example.com/
# 使用远程文件名保存
curl -O https://www.example.com/index.html

常用选项:-o filename 保存到文件;-O 使用远程文件名;-v 详细输出;-I 仅头信息;-L 跟随重定向;-u user:pass 认证。

第一个 libcurl 程序

基本模式:curl_global_init(CURL_GLOBAL_ALL)curl_easy_init()curl_easy_setopt(curl, CURLOPT_URL, "https://example.com")CURLOPT_FOLLOWLOCATION 等 → curl_easy_perform(curl)curl_easy_cleanup(curl)curl_global_cleanup()。编译可用 curl-config --cc --cflags --libs -o myprogram myprogram.c

常见编程模式

HTTP POSTCURLOPT_POSTFIELDS 设置 POST 数据,可选 CURLOPT_POSTFIELDSIZE内存中处理响应 :设置 CURLOPT_WRITEFUNCTIONCURLOPT_WRITEDATA,在回调中 realloc 并追加数据。HTTPS :使用 https:// URL;可设 CURLOPT_CA_CACHE_TIMEOUT;生产环境勿关闭 CURLOPT_SSL_VERIFYPEER/CURLOPT_SSL_VERIFYHOST错误处理 :检查 curl_easy_perform() 返回的 CURLcode,用 curl_easy_strerror(res) 获取描述。调试curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L) 或命令行 curl -v


构建与安装

从源码构建 curl 与 libcurl 的典型步骤:运行 ./buildconf(若从 git 克隆)、./configure(可加 --with-openssl--with-nghttp2 等以启用 TLS、HTTP/2),然后 makemake testmake install。不同平台与包管理器(如 vcpkg、Homebrew)也提供预编译包。详细选项与依赖说明见官方 INSTALL 文档与仓库 docs/


基本用法示例

libcurl Easy 接口遵循统一生命周期:全局初始化curl_global_init)→ 创建句柄curl_easy_init)→ 配置选项curl_easy_setopt)→ 执行传输curl_easy_perform)→ 清理句柄curl_easy_cleanup)→ 全局清理curl_global_cleanup)。全局初始化一次,每次传输创建并清理 easy handle。

简单 HTTP GET :设置 CURLOPT_URLCURLOPT_FOLLOWLOCATION(跟随重定向),调用 curl_easy_performHTTP POST :设置 CURLOPT_POSTFIELDSCURLOPT_POSTFIELDSIZE,libcurl 自动使用 POST 方法。HTTPS :使用 https:// URL;可设 CURLOPT_CA_CACHE_TIMEOUT 缓存 CA;生产环境勿关闭 CURLOPT_SSL_VERIFYPEER/CURLOPT_SSL_VERIFYHOST下载到文件 :通过 CURLOPT_WRITEFUNCTION 注册回调,在回调中用 fwrite 写入 CURLOPT_WRITEDATA 传入的 FILE*内存中捕获响应 :写回调中对用户提供的缓冲区 realloc 并追加数据,返回已处理字节数。


命令行选项参考

curl 命令行工具提供超过 200 个选项,用于控制传输行为、身份验证、协议处理与输出格式。本参考介绍选项的架构与最常用选项的要点。

选项架构概述

选项通过集中式解析系统解析,将选项名称映射到内部配置结构。每个选项具有:长形式 (如 --verbose)、短形式 (如 -v)、参数类型 (字符串、文件、布尔或无)、标志 (TLS 相关、已弃用、全局、互斥等)、多次使用行为(单次、追加、布尔、互斥、每 URL 等)。

选项语法与用法

短选项:单破折号加一字母(-v);长选项:双破折号加名称(--verbose)。短选项可组合:-vOL 等同 -v -O -L。布尔选项可用 no- 前缀禁用:--no-verbose。等号语法:--output=file-- 表示选项结束,其后为 URL。@filename 从文件读取参数,@- 为 stdin。

帮助系统

--help 显示重要选项;--help <category> 按类别显示。类别包括:auth、connection、curl、dns、ftp、global、http、output、post、proxy、timeout、tls、upload、verbose。--help -v--help --verbose 查看特定选项;--help all 列出全部。

输出选项

  • --output (-o) :写入指定文件;支持 # 加数字的变量替换与 globbing;多 URL 可多次 -o- 表示 stdout;可用 /dev/null--out-null 抑制响应体。
  • --remote-name (-O) :以远程路径的文件名保存到当前目录;多 URL 可多次 -O;8.10.0 起若 URL 以斜杠结尾则使用最后目录名或 curl_response;可用 --output-dir 指定目录。

数据传输选项

  • --data (-d) :以 application/x-www-form-urlencoded 发送 POST 数据;多次使用用 & 合并;@file 从文件读,@- 从 stdin;--data-raw 不解释 @--data-binary 发送二进制。
  • --header (-H) :添加或覆盖 HTTP/IMAP/SMTP 头;空值可删除内部头;@file 从文件读头;敏感头(如 Authorization、Cookie)在重定向到不同源时默认不转发(除非 --location-trusted)。

配置与 URL、认证

  • --config (-K) :从文件或 stdin 读取参数;格式为每行一选项,可用 # 注释;默认会检查 $CURL_HOME/.curlrc$HOME/.curlrc 及 Windows 对应路径等。
  • --url :指定 URL;无方案时按主机名猜测协议(ftp.example.com→FTP,否则→HTTP);8.13.0 起支持 --url @urls.txt 从文件加载 URL。
  • --user (-u) :服务器认证,格式 user:password;仅 user 时提示输入密码;Windows SSPI 可用 -u :

诊断与全局/每 URL

  • --verbose (-v) :详细输出;-vv-vvv-vvvv 逐级增加跟踪;--trace-config 可精细控制。注意详细输出可能包含凭据与内容。
  • 全局选项 (如 --config--verbose--help--version)作用于所有操作;每 URL 选项 作用于下一个 URL;--next 分隔 URL 组并重置每 URL 状态。

选项按功能分组约:Connection、DNS、HTTP、Authentication、TLS/SSL、Output、Proxy、FTP、协议相关、Timeout、Upload、Verbose、Global 等。完整文档请用 --help all 或查阅 man 手册。


最新更新

2026 年 1 月期间 curl 项目活动频繁:重大架构调整、协议支持决策与大量错误修复。

主要变更

移除 OpenSSL-QUIC 支持 :项目已移除对 OpenSSL 内置 QUIC 的支持,理由包括:与替代方案相比更慢、更耗内存、在 curl 中仅实验性;部分 OpenSSL-QUIC 测试因不稳定被禁用;OpenSSL 侧重视不足;无人主张保留。使用原生 OpenSSL 构建的用户可通过 ngtcp2 后端继续获得 HTTP/3 支持。

协议架构重构 :方案信息与协议实现分离------方案信息位于 struct Curl_scheme,各协议实现的函数指针位于 struct Curl_protocol;URL API 现始终支持所有已知协议。构建可识别所有方案但仅包含实际内置实现,多协议可复用相同设置与函数(TLS/非 TLS),减少 26+ 协议间的重复代码。

调试构建简化 :TrackMemory (CURLDEBUG) 合并到启用调试的构建中;移除独立配置、废弃 CURL_VERSION_CURLDEBUG 改用 CURL_VERSION_DEBUG、内部宏重命名为 CURL_MEMDEBUG

面向用户的增强

速率限制小数支持--limit-rate 2.5k--max-filesize 3.7M 等支持小数,便于更细粒度控制。文档更新 :INSTALL 默认 libpsl 要求、MQTT 文档移除 mqtts 限制说明、Apple 目标 -Wl,-dead_strip 建议等。

错误修复与稳定性

信号处理 :多线程场景下对空 multi handle 反复调用 curl_multi_perform() 导致 sigaction() 频繁调用、CPU 升高的问题已修复,通过引入 struct Curl_sigpipe_ctx 延迟 sigpipe 处理。编译器 :解决 Apple clang 17 C89 下 -Wcomma 警告及罕见配置下的不可达代码警告。协议 :IMAP、构建配置(如 --disable-aws)等有修复。

CI 与构建

构建大小跟踪加入 CI;CMake 与 Apple 框架、INSTALL-CMAKE 文档、autotools 帮助缩进等有改进;GitHub Actions 中 Linux 最小化作业名称加入 CPU 架构便于识别。

当前已知问题(截至 2026 年 1 月)

部分未决问题需留意:ngtcp2 下 HTTP/3 失败而 quiche 正常(#20324);FTP 使用 CURLOPT_NOBODY 可能意外触发 TYPE A/LIST(#20352);IMAP 列出文件在 8.18.0 回退(#20356);TIMEOUTCONNECT_ONLY 同时设置导致 8.17.0 超时(#20347);CURL_DISABLE_VERBOSE_STRINGS 下跟踪字符串仍保留(#20341);8.17.0 长时间连接后请求失败(#20105)等。项目持续聚焦稳定性、可维护性与开发者体验。


问题与反馈

curl 代码库长期稳定,但 GitHub 上 2026 年 1 月的反馈反映出多线程信号处理、超时与连接管理回归、HTTP/3 实现差异等边缘情况。

信号处理性能(多线程)

在大量线程的进程中,对空 multi handle 反复调用 curl_multi_perform() 会导致高 CPU(如 10k 线程约 27%、100k 线程 220%+),根因是连接池内部未设置 CURLOPT_NOSIGNAL,每次调用都执行 sigaction(),在 Linux 上随线程数线性恶化。项目通过引入 struct Curl_sigpipe_ctx 延迟 sigpipe 处理予以修复;用户可采取的变通是在无待处理请求时跳过 curl_multi_perform()

超时回归与选项冲突

8.17.0 中 CURLOPT_TIMEOUTCURLOPT_CONNECT_ONLY 同时使用会持续超时(#20347):Curl_timeleft()connect_only 时返回 0,后续逻辑误判超时。行为在 7.84.0--8.17.0 间变化,文档未提示两选项不兼容,对依赖"带超时的仅连接"场景有破坏性。

HTTP/3 与后端差异

不同 HTTP/3 后端表现不一。有用户在使用 ngtcp2 栈时连接失败(TLS 握手/错误码 368),而旧版 quiche 正常(#20324)。项目因此移除 OpenSSL-QUIC 支持,将用户导向 ngtcp2 等更可维护的后端。

FTP、IMAP 与协议边缘情况

FTPCURLOPT_NOBODY 在 FTP 下可能意外触发 TYPE A 和 LIST,导致无写回调时 CURLE_WRITE_ERROR(#20352)。IMAP :字面量 {size} 在引号内未被正确忽略,触发错误解析(#20320),已通过简化 imap_is_bchar() 修复。

二进制大小、HTTP/2/3 细节与构建

二进制--disable-verbose 不会从二进制中移除跟踪字符串,因参数仍被传递(#20341);改进需从宏/实现层面处理。HTTP/3 头部规范化 (#20338)、HTTP/2 RST_STREAM 代码 (#20239,STREAM_CLOSED vs CANCEL 与部分 CDN 互操作)等暴露实现细节差异。构建:CMake ZLIB 属性、autotools 帮助缩进等有小问题(#20313、#20342)。

连接池回归与文件/重定向

#20105 报告 8.17.0 在长时间运行、multi + 连接池配置下请求逐渐失败,8.15.0 正常,疑为连接管理或连接过滤器回归。Content-Disposition 无文件名时 curl 未从重定向 URL 提取文件名(#20318),与 wget 行为不同,项目按功能请求处理。

总体可见:线程安全与信号处理的扩展性、多协议边缘情况、HTTP/3 生态碎片化、选项组合与长时间运行的回归测试覆盖、以及多构建系统维护负担,是当前问题反馈中反复出现的主题。问题与建议可通过 GitHub Issues 提交。


关于贡献者

curl 由多元化开发者维护,贡献涵盖关键 bug 修复与架构重构。

核心贡献者

Daniel Stenberg (创始人兼首席维护者):近期包括将 scheme 信息与协议实现分离、用 strchr() 简化 IMAP 解析、为 --limit-rate/--max-filesize 增加小数支持、以及基于性能与维护考量移除 OpenSSL-QUIC 支持;用户仍可通过 ngtcp2 使用 QUIC。

Viktor Szakats:构建系统与 CI(合并 TrackMemory 到调试构建、修复罕见配置下的不可达代码、添加二进制大小跟踪)、平台相关(Apple clang -Wcomma、CMake Apple 框架、-Wl,-dead_strip 建议)、文档与 autotools/cmake 修正。

Stefan Eissing :引入 struct Curl_sigpipe_ctx 延迟 sigpipe 处理,缓解多线程下对空 multi handle 调用 curl_multi_perform() 导致的 sigaction/CPU 问题(#20326)。

其他贡献者与问题报告

Maksim Ściepanienka(--disable-aws 构建修复)、tommy(sigpipe 中取消 SA_SIGINFO)、Arnav-Purushotam-CUBoulder(INSTALL 与 libpsl/TLS 文档)、Sascha Frinken(MQTT 文档移除 mqtts 限制)等。社区通过带复现与分析的 issue 推动优先级(如 sigaction 性能、HTTP/3、IMAP 字面量、HTTP/2 RST_STREAM 等)。

贡献模式与参与

近期模式:构建/CI 持续维护、信号处理仍复杂、协议有进有退(如 MQTT TLS 完成、OpenSSL-QUIC 移除)、文档与平台特定工作繁重。贡献形式包括 bug 修复、构建/CI、文档、测试与带最小复现的 issue。完整名单见仓库贡献者统计与提交历史。


架构概述

本页概述 libcurl 的核心组件、设计模式及其协同方式,以提供灵活、高性能的传输能力。

高层架构

libcurl 采用分层架构 ,在公共接口、连接管理与协议实现之间有清晰界限,强调连接复用、模块化协议支持与可扩展过滤。四层为:公共 API 层 (Easy 与 Multi 接口)、传输管理层 (传输状态、调度与协调)、连接层 (连接、连接池与网络操作)、协议层(各协议实现与过滤器)。

核心组件

Easy 接口 :同步、阻塞 API,适合单次传输。每个 Easy 句柄(CURL)代表一次完整传输。生命周期:curl_easy_init()curl_easy_setopt()curl_easy_perform()curl_easy_cleanup()。特点:每传输一句柄、API 简单、默认阻塞、自动连接管理。

Multi 接口:通过统一事件驱动模型实现异步、并发传输。Multi 句柄(CURLM)管理多个 Easy 句柄,配合 I/O 多路复用。内部实现复杂状态机,跟踪 INIT、RESOLVING、CONNECTING、PROTO_CONNECTING、DO、PERFORMING、DONE、FAILED 等状态,处理连接建立、协议协商、数据传输与清理。

连接管理系统

连接池(cpool):按目标(协议族、主机与端口、代理、TLS 参数、认证)分组连接,实现智能复用。结构包括 dest2bundle(按目标分组的哈希表)、num_conn、next_connection_id、idata 等(见 conncache.h)。

连接过滤系统(cfilters):可堆叠的过滤器链(如 应用 → Easy → 传输层 → HTTP/2 → TLS → PROXY → SOCKET → 网络)。操作包括 connect、send、recv、close、adjust_pollset,支持通过 SOCKS 代理的 TLS HTTP/2 等组合。

传输层与协议实现

传输层:协调应用与网络间数据移动,管理 I/O、进度与转换。设置函数如 Curl_xfer_setup_nop/send/recv;透明处理编码(分块、gzip)、认证、重定向与时间条件。

协议:模块化支持 26 种协议。协议族示例:HTTP(HTTP/2、HTTP/3 多路复用)、FTP、SSH(SCP、SFTP)、SMTP、POP3、IMAP。每协议实现标准回调:连接建立、请求准备、响应解析、数据传输、连接拆除。

TLS、内存与线程安全

TLS 后端:可插拔,支持 OpenSSL、GnuTLS、mbedTLS、WolfSSL、Schannel、Secure Transport、Rustls;vtls_scache 提供会话缓存(如 CURL_TLS_SESSION_SIZE = 25)。

内存:可自定义分配器(curl_global_init_mem),便于跟踪与泄漏检测。资源清理:Easy 句柄单独、Multi 共享、连接池 LRU、共享句柄(DNS 缓存、SSL 会话)。

线程安全:CURL_GLOBAL_NOTHING/SSL/WIN32/ALL 可选;共享句柄可安全共享 DNS 缓存、SSL 会话与连接池。

性能、错误与扩展

性能:连接复用、HTTP/2 多路复用、流水线、异步 DNS、零拷贝倾向;Multi 使用哈希传输表(CURL_XFER_TABLE_SIZE = 512)做 O(1) 查找。

错误:CURLcode(Easy)、CURLMcode(Multi)、协议与套接字错误;调试构建含魔数校验、状态机与套接字日志。

扩展点:自定义协议、连接过滤器、回调、内存分配器、套接字回调;过滤器可做加密、流量整形、协议转换、调试/代理,HTTP/3 即通过过滤器实现。

设计原则:可移植性、最小依赖、向后兼容、性能与安全;构建时可选协议、TLS 后端、功能标志与大小优化,便于嵌入式最小构建。


libcurl API 设计

libcurl API 采用分层设计,兼顾简单阻塞与高并发事件驱动场景;理念是渐进式披露:从 Easy 单传输起步,再过渡到 Multi、Share、URL 等更复杂模式,在保持向后兼容的前提下不膨胀 API。

核心接口架构

Easy 接口 :围绕不透明句柄 CURL*,提供初始化→配置→执行→清理的生命周期;通过 curl_easy_setopt() 接受 300+ 选项,在单一函数签名下实现细粒度控制;句柄封装传输状态、选项、回调与连接上下文。

Multi 接口 :面向非阻塞、并发传输;由应用驱动执行(何时 perform)。CURLM* 管理多个 Easy 句柄;支持 curl_multi_perform()(select/poll)与 curl_multi_socket_action()(与 libevent/libev/epoll 等事件循环集成,可扩展至数千连接)。

Share 接口 :多 Easy 句柄共享 DNS 缓存、TLS 会话、连接池、cookies 等;CURLSH* 需在多线程下注册 lock/unlock 回调,libcurl 不提供内置同步。

URL 接口 (7.62.0+):CURLU* 表示 URL 结构化对象,可安全操作 scheme、host、path、query、fragment,避免手写解析与常见 URL 漏洞;支持编码/解码与 Unicode。

句柄生命周期与内存管理

Easy:curl_easy_init() 分配 Curl_easy(含状态、选项、连接、回调),curl_easy_setopt() 配置,curl_easy_perform() 执行,curl_easy_cleanup() 释放;curl_easy_reset() 可重置选项但保留缓存。Multi 内部维护传输表、状态机、socket 监控、连接与 DNS/TLS 缓存;每个 easy 经 init→connect→send→receive→done。所有权 :调用者拥有句柄并负责释放;通过 getter 得到的数据需用 curl_free() 释放。可经 curl_global_init_mem() 安装自定义分配器。

配置与回调、错误处理

配置 :选项以 CURLoption 枚举与 curl_easy_setopt(handle, option, value) 设置;类型有 CURLOT_LONG、CURLOT_STRING、CURLOT_SLIST、CURLOT_CBPTR、CURLOT_BLOB 等;运行时可通过 curl_easy_option_by_name/by_id/next 内省。回调 :写回调(接收数据)、读回调(上传数据,支持 ABORT/PAUSE)、进度、头部、socket 打开/关闭/sockopt;Multi 的 socket 与 timer 回调用于事件循环集成。错误 :CURLcode/CURLMcode/CURLSHcode/CURLUcode;句柄在错误后通常仍可重用或清理;curl_easy_strerror() 等提供描述;部分传输可用 CURLOPT_RESUME_FROM 恢复;回调返回值可触发特定错误(如写回调导致 CURLE_WRITE_ERROR)。


简易句柄生命周期

Easy Handle 是 libcurl 中管理单次传输的基础抽象;理解其创建、配置、执行与清理对构建稳健应用至关重要。

核心架构

Easy handle 由 struct Curl_easy 体现,聚合用户配置(UserDefined)、运行时状态(UrlState)与信息数据(PureInfo)。设计为可复用,配置与运行时状态分离,防止顺序操作间状态泄漏。每 handle 有唯一 id,便于多 handle 时调试。

生命周期阶段

初始化curl_easy_init() 确保全局已初始化,通过 Curl_open() 分配 Curl_easy、初始化子组件(元数据哈希、头/URL 缓冲区、连接池等),Curl_init_userdefined() 设置选项默认值。全局初始化有引用计数,需与清理调用平衡。

配置curl_easy_setopt() 将选项写入 UserDefined;选项可任意顺序设置,验证在执行时延迟。字符串由 libcurl 复制并拥有,应用设置后即可释放己方副本。选项类别包括 URL/协议、网络、认证、传输、回调、TLS 等。

传输执行curl_easy_perform() 内部创建临时 multi handle、添加本 easy、按 multi 架构运行;经历 Init→Protocol→Connect→Do→Done 状态机。期间管理连接(新建或复用)、DNS、TLS、数据与进度回调。返回 CURLcode,可用 curl_easy_strerror() 或 handle 信息获取详情。

复制与重置curl_easy_duphandle() 深拷贝选项与 cookie/HSTS/ALTSVC 等,生成独立副本用于并行传输;副本不共享传输状态。curl_easy_reset() 将 handle 还原为"新初始化"状态(清空选项与运行时状态),仅应在未处于 perform 中的 handle 上调用。

清理curl_easy_cleanup() 释放连接、SSL 会话、动态内存与 handle 本身;每个 curl_easy_init() 必须对应一次 cleanup。


简易选项配置

easy 选项系统通过类型安全、可扩展的机制配置传输,包含超过 328 个选项,涵盖协议、认证、超时与数据处理。

选项类型系统

选项按 curl_easytype 九类分类,决定存储、验证与处理方式;Curl_vsetopt() 按类型将选项路由到专用处理程序,实现 O(1) 分发与类型安全。

选项元数据与 Setopt 分发

Curl_easyopts[] (由 optiontable.pl 生成)记录每个选项的 name、id、type、flags;支持 curl_easy_option_by_name()curl_easy_option_by_id()curl_easy_option_next() 自省。curl_easy_setopt() 按值类型范围(OBJECTPOINT、FUNCTIONPOINT 等)分发,避免巨型 switch,且允许在回调内调用以实现动态配置。

按类别配置

  • 字符串 (CURLOT_STRING):复制或引用语义;CURLOPT_URL、CURLOPT_USERAGENT、CURLOPT_USERNAME/PASSWORD、CURLOPT_COOKIE 等由 Curl_setstropt() 等处理。
  • 长整型 (CURLOT_LONG):超时、标志、缓冲区;由 setopt_long_* 按网络/SSL/代理/HTTP/协议/杂项分发;如 CURLOPT_TIMEOUT、CURLOPT_CONNECTTIMEOUT、CURLOPT_VERBOSE、CURLOPT_FOLLOWLOCATION。
  • 值枚举 (CURLOT_VALUES):CURLOPT_HTTPAUTH、CURLOPT_HTTP_VERSION、CURLOPT_SSLVERSION、CURLOPT_PROXYTYPE 等;按允许的位掩码与构建能力验证。
  • 回调 (CURLOT_FUNCTION):WRITEFUNCTION、READFUNCTION、HEADERFUNCTION、PROGRESSFUNCTION、DEBUGFUNCTION 等,配对应 *DATA (CURLOT_CBPTR) 传用户上下文。
  • 大文件 (CURLOT_OFF_T):curl_off_t,如 CURLOPT_INFILESIZE_LARGE、CURLOPT_RESUME_FROM_LARGE。
  • 字符串列表 (CURLOT_SLIST):CURLOPT_HTTPHEADER、CURLOPT_QUOTE、CURLOPT_RESOLVE、CURLOPT_MAIL_RCPT 等;setopt_slist 管理所有权。
  • Blob (CURLOT_BLOB):curl_blob(data/len/flags),CURLOPT_SSLCERT_BLOB、CURLOPT_SSLKEY_BLOB 等;按 CURL_BLOB_COPY/NOCOPY 管理内存。

验证与持久化

类型/范围/长度/枚举/构建能力多级验证;不支持的选项返回 CURLE_NOT_BUILT_IN。curl_easy_reset() 恢复默认选项但可保留连接池;curl_easy_duphandle() 复制选项配置供多线程等场景使用。


简易执行机制

curl_easy_perform() 是 Easy 接口的同步执行模型:阻塞直到传输完成,内部通过委托给 Multi 接口实现------每次调用会重用或创建专用 multi handle,附加 easy handle,用 Multi 状态机执行传输;multi 缓存在 data->multi_easy,实现连接池与资源共享。

Multi Handle 与执行路径

执行时先确认 easy 未被其他 multi 使用,从 data->multi_easy 复用或新建 multi(单传输优化的最小哈希表配置)。multi 在传输之间持续存在,通过 cpool 启用连接复用;仅在 curl_easy_cleanup() 时销毁。

标准阻塞路径:easy_transfer() 实现轮询与执行循环,反复调用 curl_multi_perform() 直到运行中 handle 数为 0 或出错;curl_multi_poll() 使用 1000ms 最大等待,定时器管理保证有工作时快速唤醒。

基于事件的路径:DEBUGBUILD 下 easy_events() 使用 socket 回调 API 与 Curl_poll(),用于调试/测试;生产异步场景应直接用 curl_multi_socket_action()。

状态机与传输循环

核心逻辑在 multi_runsingle() 的 18 状态有限状态机中:MSTATE_INIT(验证 URL、加载 cookie)→ SETUP → CONNECT → RESOLVING/CONNECTING → PROTOCONNECT/PROTOCONNECTING → DO/DOING/DOING_MORE → DID → PERFORMING(Curl_sendrecv 数据收发)→ RATELIMITING → DONE → COMPLETED。状态通过 multistate() 更新;可返回 CURLM_CALL_MULTI_PERFORM 表示需立即再次执行。

MSTATE_PERFORMING 期间 Curl_sendrecv() 根据 KEEP_RECV/KEEP_SEND 协调收发,通过 sendrecv_dl/sendrecv_ul 与连接过滤器链交互。轮询经 curl_multi_poll() 聚合所有活动 socket,并结合 Curl_expire() 定时器计算下次超时。完成时 multi_done() 排队完成消息,easy_transfer() 用 curl_multi_info_read() 取 CURLcode 并 remove_handle,但保留 multi 供后续复用。


多句柄架构

多句柄架构使 libcurl 在单线程内高效管理多个并发传输,提供事件驱动接口,在保持对 I/O 完全控制的同时利用状态机与连接池。

核心多句柄结构

struct Curl_multi 是所有并发传输的协调器,含魔术标识符用于验证。传输通过 xfers 哈希表跟踪,按状态分为四个位集:process(正在处理)、dirty(需立即关注)、pending(因连接限制等待)、msgsent(已完成待通知);实现 O(1) 状态查找与批量操作。共享资源包括 DNS 缓存、TLS 会话池、连接池 cpool (受 max_host_connections、max_total_connections 限制)、消息队列 msglist定时器树 timetree

Multi 状态机与生命周期

CURLMstate 共 19 状态:MSTATE_INIT → SETUP → RESOLVING/CONNECTING → PROTOCONNECT/PROTOCONNECTING → DO/DOING/DOING_MORE → PERFORMING → RATELIMITING → DONE → COMPLETED → MSGSENT。与 easy 连接状态机不同,multi 状态机在传输级别协调哪些传输应被处理。

添加 :curl_multi_add_handle() 验证并初始化传输状态,分配唯一 ID,放入 pending。执行 :multi_runsingle() 按当前状态执行处理程序并返回 CURLMcode。完成:multi_done() 清理资源、决定连接关闭或回池,并准备完成消息。

事件通知与执行模型

套接字回调 (curl_socket_callback):套接字状态变化时调用,参数含 easy、fd、事件类型(CURL_POLL_IN/OUT/INOUT/REMOVE)与用户指针,便于接入 select/poll/事件循环。定时器回调(curl_multi_timer_callback):通知下次调用 curl_multi_socket_action()/perform() 前可等待的最长时间;内部用 timetree 管理。

三种执行模型:① 简单轮询:curl_multi_perform() 执行尽可能多的 I/O 不阻塞,返回运行中句柄数。② Select/Poll:curl_multi_fdset() 填充 fd_sets;curl_multi_wait()/curl_multi_poll() 统一轮询 libcurl 与自定义 fd。③ 事件驱动:curl_multi_socket_action(sock, event) 仅处理指定就绪套接字,配合 CURLMOPT_SOCKETFUNCTION/TIMERFUNCTION 接入事件循环。

消息队列与连接池

完成时生成 CURLMsg(CURLMSG_DONE、easy 指针、结果码)入 msglist;curl_multi_info_read() 按 FIFO 取消息。cpool 与 multi_done() 配合实现连接复用;支持 HTTP/1.1 keep-alive 与 HTTP/2 多路复用;CURLMOPT_PIPELINING 控制管道。唤醒:curl_multi_wakeup()(ENABLE_WAKEUP 平台)可中断阻塞的 poll/wait。缓冲区:xfer_buf、xfer_ulbuf、xfer_sockbuf 可重用,带借用状态防并发使用。


并发传输

libcurl 的并发传输允许在单线程内高效执行多个同时进行的网络操作;multi 接口可从少量传输扩展到数千个并发连接,同时保持对执行与资源的控制。

Multi 接口架构

单个 multi 句柄 协调多个 easy 句柄:每个 easy 代表一次独立配置的传输,multi 负责编排执行、连接池与状态管理。状态机通过 MSTATE_* 系列状态跟踪每次传输(INIT→PENDING→SETUP→CONNECT→RESOLVING/CONNECTING→PROTOCONNECT/PROTOCONNECTING→DO/DOING/DOING_MORE→DID→PERFORMING→RATELIMITING→DONE→COMPLETED→MSGSENT)。multi 维护传输表(uint32 哈希)、process/dirty/pending/msgsent 位集、消息列表与定时器树,以最小开销跟踪大量并发传输。

操作基础与工作流

multi 采用拉取模型:应用显式控制 libcurl 何时执行工作。流程:curl_global_init → curl_multi_init → 为每次传输 curl_easy_init + setopt → curl_multi_add_handle → 主循环(curl_multi_perform → curl_multi_poll 等待 → curl_multi_info_read 检查完成 → remove_handle + easy_cleanup)→ curl_multi_cleanup → curl_global_cleanup。两种用法:面向 select 的 perform + poll,或基于事件的 multi_socket(curl_multi_socket_action + 回调)。

传输管理与连接池

每次传输有唯一 mid,由四个位集分类:process(正在处理)、dirty(需立即处理)、pending(等待连接等资源)、msgsent(完成消息已交付)。dirty 机制使 libcurl 自动识别需处理的传输,应用只需调用 perform。完成信息经 curl_multi_info_read() 的 CURLMSG_DONE 与结果码获取;完成句柄应先 remove_handle 再 cleanup。

连接池:按目标缓存连接,复用 TCP/TLS;CURLMOPT_MAXCONNECTS、CURLMOPT_MAX_HOST_CONNECTIONS、CURLMOPT_MAX_TOTAL_CONNECTIONS 限制缓存与并发;CURLMOPT_PIPELINING 启用 HTTP 多路复用。DNS 与 TLS 会话在 multi 级别缓存,供所有传输复用。

基于事件的 multi_socket

CURLMOPT_SOCKETFUNCTION 与 CURLMOPT_TIMERFUNCTION 将 libcurl 接入 libevent/epoll 等事件循环:套接字回调通知需监控的 fd 与读/写需求,定时器回调提供下次调用前的最大等待时间,实现高性能、可扩展的并发传输。


基于事件的操作

multi 接口的基于事件操作通过与 libevent、libev、kqueue、epoll 等外部事件循环集成,以反应式方式管理大量并发连接,避免持续轮询。

核心架构

回调驱动:libcurl 通过套接字回调和定时器回调通知应用需监控的 fd 与超时;应用在事件发生时调用 curl_multi_socket_action() 响应。multi 内部事件子系统(struct curl_multi_ev)用哈希表跟踪套接字状态,与事件循环协调。

套接字回调(curl_socket_callback):在需监控新套接字或变更监控要求时调用,参数含 easy、fd、事件掩码(CURL_POLL_IN/OUT/INOUT/REMOVE)与用户数据。CURL_POLL_REMOVE 时应用须停止监控该 fd。mev_sh_entry.xfers 记录使用该套接字的传输;套接字活动时 Curl_multi_ev_dirty_xfers() 将受影响传输标为 dirty。

定时器回调(curl_multi_timer_callback):在需因内部超时(连接超时、速率限制等)被调用时通知应用,参数为 multi、超时毫秒数、用户数据。应用设置定时器,到期时以 CURL_SOCKET_TIMEOUT 调用 curl_multi_socket_action()。超时信息存于 timetree(伸展树),由 Curl_update_timer() 动态更新。

套接字操作与 Pollset

curl_multi_socket_action(sock, event) 是事件驱动主入口;multi_socket() 对受影响的传输执行 I/O,dirty 集中的传输经 multi_runsingle() 推进状态机。Curl_multi_ev_assess_xfer() 评估传输状态并确定需监控的 I/O,结果存于 easy_pollset;mev_pollset_diff() 检测变更并仅对变更调用套接字回调。mev_sh_entry 维护 readers/writers 引用计数以支持多路复用下多传输共享单套接字。

生命周期与唤醒

套接字以 fd 为键的哈希表管理;mev_sh_entry_add() 创建/获取条目,mev_forget_socket() 移除;curl_multi_assign() 可关联套接字与私有数据。curl_multi_wakeup() 在支持平台写入套接字对/管道/eventfd,使事件循环立即返回,便于在等待时添加新 easy handle。Windows 用 WSAEventSelect(),Unix(ENABLE_WAKEUP)用套接字对或 eventfd。

对比:multi socket 仅处理有活动的套接字,可扩展到数千连接、定时器自动管理、多路复用支持更好;multi perform + fdset 需手动管理 fd 集与超时,适合几十个连接以内的简单场景。


HTTP 协议实现

curl 的 HTTP 实现构成所有 HTTP/HTTPS 传输的基础,对 HTTP/1.0 与 HTTP/1.1 提供完整支持,并与 HTTP/2、HTTP/3 集成;架构上分离请求构建、响应解析与协议状态管理。

架构与版本协商

模块化设计:协议处理器接口使 HTTP/1、HTTP/2、HTTP/3 实现共存并共享语义;http.c 提供通用功能(认证、重定向、头部管理)。版本协商由 http_negotiation 管理:rcvd_min、wanted、allowed、preferred、h2_upgrade、h2_prior_knowledge、accept_09、only_10 等。Curl_http_neg_init() 将 CURL_HTTP_VERSION_* 映射到版本集合(如 HTTP_VERSION_2_0 支持 1.x+2 与升级,HTTP_VERSION_3 支持 1.x/2/3)。

请求构建

httpreq 含 dynhds headers/trailers、scheme、authority、path、method。请求类型由 Curl_HttpReq 枚举(HTTPREQ_GET/POST/POST_FORM/POST_MIME/PUT/HEAD)。请求头按 http_hd_t 定义顺序组装。

响应解析与头部

状态行按 RFC 9112 解析版本与状态码;支持 HTTP/1.0、1.1、2、3 格式;CURLOPT_HTTP200ALIASES 可配置状态别名。头部按首字符分发(http_header_a/c/l/p/r/s/t/w 等)处理 Alt-Svc、Content-*、Connection、Location、Set-Cookie、Transfer-Encoding、WWW-Authenticate 等。Content-Length 做一致性校验与大小限制。

认证与重定向

认证方案:CURLAUTH_BASIC、DIGEST、NEGOTIATE、NTLM、BEARER、AWS_SIGV4;pickoneauth() 按优先级(Negotiate > Bearer > Digest > NTLM > Basic > AWS_SIGV4)选择。重定向:301/302/303 默认 POST→GET,307/308 保持方法,由 CURLOPT_POSTREDIR 覆盖;followtype 区分 FOLLOW_FAKE/RETRY/REDIR。跨主机/方案重定向时自动清除凭据,除非 CURLOPT_UNRESTRICTED_AUTH。

连接管理

Keep-Alive:HTTP/1.0 默认关闭、靠 Connection: keep-alive 保持;HTTP/1.1 默认保持、靠 Connection: close 关闭。连接在收到 Connection: close、无 keep-alive 的 1.0 响应或 1.1 无 Connection 且无 keep-alive 等情况下关闭;与连接池与复用机制集成。


HTTP/2 和 HTTP/3 支持

本页涵盖 HTTP/2/HTTP/3 的架构、后端集成、协议协商与连接过滤器集成。

HTTP/2 架构

HTTP/2 通过 nghttp2 实现,经连接过滤器系统集成;Curl_cft_nghttp2 将 TCP/TLS 连接转为多路复用 HTTP/2 会话,使用 nghttp2 的会话管理、流控制与头部压缩。要点:连接窗口 10MB、每流 10MB(可配置)、16KB DATA 帧块、默认 100 并发流;自定义内存分配回调以集成 curl 内存跟踪。支持 ALPN(HTTPS)与 HTTP/1.1 升级(HTTP)。

HTTP/3 与 QUIC

HTTP/3 基于 QUIC,多后端:ngtcp2 (稳定,OpenSSL 3.5+/quictls/GnuTLS/wolfSSL)、quiche (实验性,BoringSSL)、OpenSSL QUIC (实验性)。Curl_cft_http3 扩展连接过滤器;各后端实现 QUIC 特定逻辑,支持 UDP GSO、QLOG、超时写阻塞等。

协议选择与协商

命令行:--http2(ALPN/升级)、--http3(尝试 HTTP/3 并回退)、--http3-only、--http2-prior-knowledge。--http3 使用"HTTP 探测"回退(类似 Happy Eyeballs):happy-eyeballs-timeout-ms 控制软超时(默认 100ms)与硬超时(200ms),以平衡 QUIC 不可用时的并行连接与慢握手。

构建与过滤器集成

ngtcp2 需 ngtcp2、nghttp3 及支持 QUIC 的 TLS;quiche 需 Rust 与 BoringSSL。HTTP/2/HTTP/3 均通过 Curl_cftype 注册(Curl_cft_nghttp2、Curl_cft_http3、Curl_cft_h2_proxy),提供 connect/send/recv/adjust_pollset 等回调;HTTP/2 在流窗口耗尽时通过 pollset 调整(移除 POLL_OUT、等待 WINDOW_UPDATE)优化流控与 CPU。


TLS 后端选择

curl 采用可插拔 TLS 后端架构,构建时选择 SSL/TLS 库,在所有后端上保持一致 API,兼顾平台、许可与安全需求。

支持的 TLS 后端

七种后端:OpenSSL (libssl/libcrypto,1.1.1+,使用最广)、GnuTLS (3.3.0+,LGPL)、mbedTLS (3.2.0+,嵌入式友好)、WolfSSL (5.5.0+,体积小)、Rustls (trustls-ffi 0.15+,Rust 内存安全)、Schannel (Windows 原生)、Secure Transport(macOS 原生)。构建时通过 CMake 或 autotools 仅选其一,或启用 CURL_WITH_MULTI_SSL/--with-multi-ssl 以在运行时选择。

架构与连接过滤器

Curl_ssl 虚表(vtls.c/vtls.h)定义各后端需实现的函数:init/cleanup、connect_blocking/connect_nonblocking、send_plain/recv_plain、close/close_all、get_internals 等。各后端(openssl.c、gtls.c、mbedtls.c 等)提供静态实例,经条件编译导出。TLS 与连接过滤器集成:ssl_connect_data 含 ssl_impl、peer、alpn、backend、negotiated、earlydata、状态与 io_need 等;SSL 过滤器位于 socket 与协议层之间,支持直接连接与 HTTPS 代理隧道。功能通过位域报告(如 SSLSUPP_CA_PATH、CERTINFO、PINNEDPUBKEY),供上层按能力使用。


TLS 会话管理

通过会话缓存与复用减少重复握手开销,支持多 TLS 后端的统一缓存接口。

架构与密钥

会话缓存在 vtls_scache.c/h,按对端(主机、IP、端口、传输类型)分组,可配置最大对端数与每对端会话数,支持 LRU 驱逐。Curl_ssl_peer_key_make() 用对端标识、TLS 后端标识、客户端证书/SRP、CA 路径哈希等生成会话密钥;:L/:G 区分本地/全局路径。

生命周期与复用

握手成功后后端通过回调(如 OpenSSL 的 ossl_new_session_cb、GnuTLS 的 gtls_handshake_cb)将会话序列化并存入缓存,含 ALPN、协议版本、QUIC 参数等元数据。查找时用 Curl_ssl_scache_take()(独占)或 Curl_ssl_scache_get_obj()(共享);按密钥与年龄校验。生存期:TLS 1.2 最长 24 小时、TLS 1.3 最长 7 天(CURL_SCACHE_MAX_*_LIFETIME_SEC)。

TLS 1.3 早期数据与配置

0-RTT 早期数据由 ssl_earlydata_state 与 ssl_connection_deferred 协调;早期数据被缓冲直至握手继续,后端在拒绝时做恢复或重协商。缓存级锁 Curl_ssl_scache_lock/unlock 保证多线程安全。配置:CURLOPT_SSL_SESSIONID_CACHE(默认启用)、CURLOPT_CONNECT_ONLY 可禁用、CURLMOPT_MAX_SSL_SESSIONS 限制缓存大小。会话与 ALPN 关联,复用时需 ALPN 兼容;与连接池协同:连接过期而会话有效时新连接可恢复会话。


证书处理

涵盖 TLS 连接中 X.509 证书验证、主机名校验与信任锚管理的完整生命周期,提供与后端无关的稳健框架。

验证架构与后端

验证在虚拟 TLS 后端之上进行,抽象各库差异、统一语义;握手期间多阶段验证。各后端按原生 API 实现:OpenSSL 系 (X509 存储、自定义 CA 文件/blob、链验证、OCSP 装订、CRL、Windows 证书存储);Schannel (Windows 证书存储 ROOT/CA/MY、自动/手动验证、CRL、指纹选客户端证书);GnuTLS (信任列表、CRL/OCSP、DANE);mbedTLS/WolfSSL/Rustls 各有验证配置与回调。

主机名与 CA 管理

Curl_cert_hostcheck() 符合 RFC 6125:DNS 名支持通配符(仅最左标签、单级、至少两段、IP 不匹配通配符);IPv4/IPv6 与 subjectAltName 比较。CA 来源:原生存储(Windows/macOS 默认)、--ca-native、CURLOPT_CAINFO、CURL_CA_BUNDLE/SSL_CERT_FILE、构建默认路径;Windows 上 OpenSSL 可导入系统存储。CA 包变更通过 SHA-256 检测,支持缓存(CURLOPT_CA_CACHE_TIMEOUT)与 multi 内共享。

链验证与吊销

链验证要求终止于受信任根、签名有效、未过期、深度与策略符合。中间证书缺失时需完整链或 AIA 获取;否则返回 CURLE_SSL_CACERT。吊销:OCSP 装订(OpenSSL、GnuTLS)、直接 OCSP 查询(有限);CRL 依后端与平台支持。生产环境应保持验证开启;客户端证书与固定见 CURLOPT_SSLCERT/SSLKEY、CURLOPT_PINNEDPUBLICKEY 等。


连接池与复用

连接池在多次传输间复用已建立连接,避免重复 TCP 握手、TLS 协商与 DNS 解析。

架构与数据结构

struct cpool 与 multi/shared handle 关联,含 dest2bundle 哈希表(目标→束)、num_conn、连接 ID 生成器、last_cleanup、locked/initialised。struct cpool_bundle 按目标(主机、端口、协议)分组,含连接链表与目标字符串。查找可复用连接为 O(1)。

生命周期与限制

添加 :Curl_cpool_add() 按目标定位/创建束、分配连接 ID、标记 in_cpool。查找 :Curl_cpool_find() 在池锁下通过 Curl_cpool_conn_match_cb 匹配(可含 TLS、认证等约束)。空闲 :Curl_cpool_conn_now_idle() 更新 lastused、在超限时关闭最旧空闲连接。终止:Curl_conn_terminate() 区分正常/中止关闭;有活动传输的连接不终止。

限制:每主机 CURLOPT_MAX_HOST_CONNECTIONS/CURLMOPT_MAX_HOST_CONNECTIONS;总连接数 CURLOPT_MAXCONNECTS/CURLMOPT_MAX_TOTAL_CONNECTIONS;Curl_cpool_check_limits() 在拒绝前按 lastused 评分关闭最旧空闲连接。

维护与线程安全

Curl_cpool_prune_dead() 每秒最多一次修剪半开/死连接;Curl_cpool_upkeep() 做 TLS/keepalive 维护;Curl_cpool_nw_changed() 在网络变更时标记连接不可复用并关闭空闲连接。池通过 CPOOL_LOCK 与 share lock(CURL_LOCK_DATA_CONNECT)实现线程安全。


传输层架构

传输层协调 easy/multi 与协议实现之间的网络 I/O,管理数据收发的完整生命周期,提供统一抽象及流控、暂停/恢复与连接绑定;介于应用接口与连接过滤器链之间。

架构与职责

通过 SingleRequest (data->req) 管理传输状态;维护 conn->send_idx/recv_idx、KEEP_SEND/KEEP_RECV,与连接过滤器链协同完成 I/O。设置函数:Curl_xfer_setup_nop()(无 I/O)、Curl_xfer_setup_send()(仅上传)、Curl_xfer_setup_recv()(仅下载)、Curl_xfer_setup_sendrecv()(双向);xfer_setup() 分配套接字索引、设置预期接收大小与方向标志,支持多套接字协议(如 FTP 控制/数据)。

生命周期与数据 I/O

生命周期:Curl_init_CONNECT() → Curl_pretransfer() → xfer_setup() → Curl_xfer_send()/Curl_xfer_recv()(可因流控暂停)→ Curl_xfer_set_shutdown() → Curl_xfer_write_done()。发送 :Curl_xfer_send(data, buf, blen, eos, pnwritten) 经 send_idx 路由,处理 CURLE_AGAIN(*pnwritten==0),累加 request_size。接收:Curl_xfer_recv() 遵守 buffer_size,数据经 recv_idx 流向写回调。

响应处理

Curl_xfer_write_resp(data, buf, blen, is_eos) 为原始响应入口,委托协议 write_resp 或直接写主体;Curl_xfer_write_resp_hd() 处理单行头部(HTTP 等);k->header 标记头部处理中。Curl_xfer_write_done(data, premature) 在传输完成时做收尾与清理。


FTP 和 SFTP 实现

FTP 与 SFTP 均支持文件操作:FTP 为双连接(命令通道 + 数据通道),SFTP 在单 SSH 连接上以二进制包多路复用。

FTP 实现

状态机 :约 28 状态,覆盖连接(FTP_WAIT220、AUTH、USER、PASS)、设置(PWD、CWD、TYPE)、传输初始化(PASV、PORT、PRET)、数据传输(LIST、RETR、STOR)、完成(QUIT、STOP);由响应码解析驱动。数据通道 :被动 PASV/EPSV(IPv6 优先 EPSV)、主动 PORT/EPRT;EPSV 响应解析格式 |||port|路径与传输:CURLOPT_FTP_FILEMETHOD 控制 MULTICWD/SINGLECWD/NOCWD;ftp_parse_url_path() 处理 URL 解码与路径拆分;上传 STOR/APPE,恢复用 REST 偏移。

SFTP 实现

基于 libssh2 :认证支持公钥、密码、agent、keyboard-interactive、host-based;私钥未指定时在 ~/.ssh/id_rsa 等标准路径查找。SSH 认证后 libssh2_sftp_init() 初始化 SFTP 子系统,提供 open/read/write 等。引用命令(sftp_quote):chmod/chgrp/chown→SETSTAT,mkdir/rm/rmdir/rename/ln→MKDIR/UNLINK/RMDIR/RENAME/SYMLINK。上传支持 WRITE/CREAT/APPEND 等标志,恢复与下载通过偏移与读接口实现。


SMTP 和 POP3 处理

SMTP 与 POP3 在统一协议架构下提供邮件发送与收取,共用 ping-pong 请求/响应框架(pingpong.h),分离连接级与请求级数据以支持连接复用。

SMTP

状态机 :SERVERGREET → EHLO/HELO → STARTTLS/UPGRADETLS → AUTH → COMMAND/MAIL/RCPT/DATA/POSTDATA → QUIT。连接后等 220,发 EHLO(失败则 HELO);解析 EHLO 得 STARTTLS、SIZE、SMTPUTF8、AUTH。认证 :统一 SASL(PLAIN、LOGIN、CRAM-MD5、DIGEST-MD5、NTLM、OAuth2),由 saslsmtp 与响应码 334/235 管理。传输 :MAIL FROM、RCPT TO、DATA;支持 AUTH/SIZE/SMTPUTF8;DATA 后 354,正文以 \r\n.\r\n 结束,行首点转义。MIME 与附件经 MIME 子系统与读取器流式处理。

POP3

问候解析含 APOP 时间戳(<timestamp@hostname>);CAPA 发现 STLS、USER、SASL。认证 :明文 USER/PASS、APOP(MD5 质询)、SASL(saslpop3 参数)。检索 :LIST(枚举/单条元数据)、RETR(完整消息);自定义命令 TOP、DELE、RSET、UIDL、NOOP;多行响应以 .\r\n 终止,no_body 控制是否传输主体。


WebSocket 支持

libcurl 将 WebSocket 实现为 HTTP/1.1 协议升级(RFC 6455),支持 ws:// 与 wss://,集成专用协议处理器与帧编解码器。

握手与帧

握手:带 Upgrade 头的 GET、16 字节随机数 base64 为 Sec-WebSocket-Key、校验 Sec-WebSocket-Accept;成功后安装 WebSocket 处理器。帧格式(RFC 6455 §5.2):FIN、RSV1--3、Opcode、MASK、Payload Length、Masking Key、Payload;Opcode 支持 CONT(0x0)、TEXT(0x1)、BINARY(0x2)、CLOSE(0x8)、PING(0x9)、PONG(0xA)。

操作模型

回调模型 :不设 CURLOPT_CONNECT_ONLY;curl_easy_perform() 阻塞。CURLOPT_WRITEFUNCTION 接收解码载荷,curl_ws_meta() 取帧元数据(类型、分片、偏移);CURLOPT_READFUNCTION + CURLOPT_UPLOAD(8.16.0+)发送,默认 BINARY,读回调中可用 curl_ws_start_frame() 控制类型与分片。CONNECT_ONLY 模型:CURLOPT_CONNECT_ONLY=2L,perform 仅建立连接后返回;之后用 curl_ws_recv()/curl_ws_send() 进行收发与帧级控制。


身份认证机制

libcurl 在 lib/vauth/ 下提供模块化认证框架,统一挑战-响应模型,支持多协议(HTTP、FTP、SMTP、IMAP、POP3 等)与多步交换(NTLM、SPNEGO);接口在 vauth.h。

Digest

digest.c / http_digest.c:支持 MD5 (RFC 2617)、SHA-256/512-256 (RFC 7616),QOP 与会话算法。Curl_auth_decode_digest_http_message() 解析 nonce、realm、algorithm、QOP、opaque;Curl_auth_create_digest_http_message() 按 HA1/HA2/response 公式生成响应,运行时选哈希。

NTLM 与明文

NTLM (ntlm.c):三消息 Type1→Type2→Type3;支持 NTLMv1/NTLMv2,优先 NTLMv2(NTLMFLAG_NEGOTIATE_NTLM2_KEY);固定工作站名、随机熵、Unicode、边界校验。明文(cleartext.c):PLAIN(authzid\0authcid\0pass)、LOGIN(用户名/密码分送)、EXTERNAL(仅用户名,依赖外部如 TLS 客户端证书);生产环境应配合 TLS。配置见 CURLOPT_USERPWD、CURLOPT_HTTPAUTH、CURLOPT_XOAUTH2_BEARER 等;代理认证单独选项。


代理支持与隧道

代理通过连接过滤器链实现,专用过滤器在请求与 Socket 之间拦截与转换流量(cfilters.h)。

HTTP 代理与 CONNECT

Curl_cft_http_proxy :根据目标协议直接转发或建立 CONNECT 隧道。CONNECT 在 cf-h1-proxy.c 中由 h1_tunnel_state 状态机管理:请求构建(Curl_http_proxy_create_CONNECT)、响应解析、407 认证、错误体分块;Method CONNECT、Authority host:port、Proxy-Authorization/Proxy-Connection/User-Agent 等。2xx 表示隧道就绪,3xx 不支持,4xx/5xx 失败。

SOCKS

socks.c 统一实现 SOCKS4、SOCKS4a、SOCKS5。SOCKS4:客户端 DNS、IP+端口;SOCKS4a:0.0.0.1+主机名+端口、代理 DNS。SOCKS5:方法协商(0 无认证、2 用户名/密码、1 GSSAPI)、连接请求支持 IPv4/IPv6/域名;可变长度响应含绑定地址。代理过滤器按状态实现 connect/send/recv/adjust_pollset,非阻塞返回 CURLE_AGAIN。配置:CURLOPT_PROXY、CURLOPT_PROXYTYPE 等。


连接过滤系统

连接过滤器(cf-*.c,cfilters.h)构成可堆叠协议栈:socket、TLS、代理(HTTP CONNECT、SOCKS)、Happy Eyeballs 等,使协议层与传输细节解耦。每层实现 Curl_cftype(connect、send、recv、close、adjust_pollset),支持非阻塞与事件驱动。详见官方 cfilters 文档


URL 解析与操作

自 7.62.0 起提供基于 CURLU 句柄的 URL API,可解析、修改与重建 URL 而无需完整传输。

架构与解析

struct Curl_URL 维护 scheme、凭据、主机、端口、路径、查询、片段等组成部分。parseurl() 流水线:Curl_junkscan 校验、Curl_is_absolute_url 识别 scheme、parse_authority() 提取登录与主机、parse_hostname_login() 与主机验证。Scheme 受 MAX_SCHEME_LEN 与已知 scheme 校验;CURLU_DEFAULT_SCHEME 缺省 https。授权 :parse_hostname_login 与 Curl_parse_login_details;主机经 ipv6_parse/ipv4_normalize/hostname_check 校验与规范化;IPv6 支持区域 ID,IPv4 接受十六进制/八进制等并规范为点分十进制。路径:dedotdotify() 做 RFC 3986 点段移除;CURLU_PATH_AS_IS 可跳过。

URL 操作 API

curl_url_get() / curl_url_set() 按 CURLUPart 读写组成部分;标志如 CURLU_DEFAULT_PORT、CURLU_NO_DEFAULT_PORT、CURLU_URLDECODE、CURLU_GET_EMPTY、CURLU_URLENCODE、CURLU_APPENDQUERY、CURLU_PUNYCODE/CURLU_PUNY2IDN。端口 1--65535 校验;设为 NULL 清除该部分。编码由 urlencode_str() 处理,查询字符串可对空格用 +。


Unix 域套接字

Unix Domain Sockets (UDS) 在类 Unix 系统上通过文件系统路径实现本地进程间通信,绕过网络栈,降低延迟并利用文件系统权限。

使用方式

命令行 :--unix-socket <path> 指定 UDS 路径,配合 HTTP URL;主机名仅用于 Host 头,不做 DNS 解析。例:curl --unix-socket /var/run/docker.sock http://localhost/images/json。套接字须已存在且可读写。libcurl:CURLOPT_UNIX_SOCKET_PATH 设路径字符串;设置后所有连接经 UDS;设为 NULL 恢复 TCP。同一句柄可在后续传输中切换。

架构与平台

经连接过滤器与 sockaddr_un (<sys/un.h>)集成;CURLOPT_UNIX_SOCKET_PATH 时使用 AF_UNIX,sun_path 为套接字路径。路径长度受 sun_path 限制(常见 108/104 字节)。平台 :HAVE_SYS_UN_H 条件编译;Linux(含抽象命名空间)、macOS、BSD 支持;Windows 无原生 UDS,WSL 下可用。安全:依赖套接字文件权限(建议 0600/0660)、目录权限与路径校验;服务器退出后清理套接字文件。


Windows 特有功能

Windows 上可使用 Schannel 作为 TLS 后端(无额外依赖)、Win32 API 集成、WSA 事件与套接字抽象等。构建与运行时注意事项(如 VC 版本、静态/动态 CRT、路径与依赖)见官方文档与 INSTALL 说明。


跨平台可移植性

curl 可在 108+ 操作系统与 28+ CPU 架构上运行,从嵌入式到大型机;通过分层配置与抽象提供一致 API 并利用平台优化。

配置架构

lib/curl_setup.h 为平台适配中心:强制最低工具链(如 VS 2010、MinGW-w64 3.0+);HAVE_CONFIG_H 时使用 curl_config.h(autoconf),否则使用平台硬编码头;处理编译器变通(如 macOS Homebrew gcc 与 availability、TARGET_OS_OSX)。各平台有专用 setup-*.h:宏、头文件顺序与编译器行为。

平台设置与抽象

Windows (setup-win32.h):Winsock 2、Watt-32、lwIP;WIN32_LEAN_MEAN/NOGDI;Vista 至 Win10 版本常量;UWP(WINAPI_FAMILY)。VMS (setup-vms.h):EBCDIC/ASCII、路径与符号名包装;OS/400 (setup-os400.h):补缺失常量与类型、isatty/puts 变通、网络与 GSSAPI 的 ASCII/EBCDIC 包装。套接字与 I/O:CURL_SCLOSE、sfcntl、swrite/sread 等宏统一 closesocket/close、send/recv 与 MSG_NOSIGNAL 等差异。移植时需关注依赖、构建配置与各 setup 头。


延伸阅读与参考链接

相关推荐
小比特_蓝光1 小时前
STL小知识点——C++
java·开发语言·c++·python
阿猿收手吧!1 小时前
【C++】格式化库:告别繁琐,拥抱高效
开发语言·c++
俩娃妈教编程1 小时前
洛谷选题:P1055 [NOIP 2008 普及组] ISBN 号码
c++·算法
悲伤小伞2 小时前
Linux_应用层自定义协议与序列化——网络计算器
linux·服务器·c语言·c++·ubuntu
llz_1122 小时前
蓝桥杯备赛-搜索(DFS/BFS)
c++·算法·蓝桥杯·深度优先·宽度优先
JaguarJack2 小时前
“Fatal error: require(): Failed opening required...” 以及如何彻底避免它再次出现
后端·php·服务端
郁闷的网纹蟒2 小时前
虚幻5---第15部分---宝藏(掉落物)
开发语言·c++·ue5·游戏引擎·虚幻
俩娃妈教编程3 小时前
洛谷选题:P1888 三角函数
c++·算法