ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

libcurl 中 curl_easy_duphandle 详解:克隆 Easy Handle 的选项继承规则与源码实现

libcurl 中 curl_easy_duphandle 详解:克隆 Easy Handle 的选项继承规则与源码实现 libcurl 中 curl_easy_duphandle 详解克隆 Easy Handle 的选项继承规则与源码实现【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl本篇技术指南围绕 libcurl 的curl_easy_duphandle()API 展开讲清克隆一个 easy handle究竟复制了什么、不复制什么。读完后你能掌握如何基于一个配置好的模板 handle 快速派生多个独立 handle典型场景是多线程中避免重复curl_easy_setopt()、哪些选项数据需要你自己保证生命周期以及该函数在 libcurl 源码中的实际克隆流程与测试覆盖。函数定位与基本用法curl_easy_duphandle是 libcurl easy 接口族的一员自 7.9 版本引入适用于所有协议用于克隆一个 easy handle。其原型定义在 include/curl/easy.h#include curl/curl.h CURL *curl_easy_duphandle(CURL *handle);它返回一个新的 curl handle其中所有此前在输入handle上设置的选项即所有curl_easy_setopt()调用所建立的状态都被复制过来。源 handle 与克隆 handle 之后可以独立使用并且两者都必须各自用curl_easy_cleanup(3)释放。头文件中的注释点明了它的典型价值在多线程序列中每个新线程克隆一次 handle即可避免在每个线程里重复一连串相同的curl_easy_setopt()调用。一个最小示例与官方文档一致int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; CURL *nother; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); nother curl_easy_duphandle(curl); result curl_easy_perform(nother); curl_easy_cleanup(nother); curl_easy_cleanup(curl); } }使用模式上它位于 handle 生命周期的中间位置curl_easy_init()创建 →curl_easy_setopt()配置 →curl_easy_duphandle()派生 →curl_easy_cleanup()销毁另可配合curl_easy_reset()清空选项。返回值与线程约束返回值如果函数返回NULL说明出错了没有返回有效 handle。从源码看lib/easy.c任何一步分配失败calloc、字符串/二进制块复制、cookie 引擎初始化、HSTS/alt-svc 初始化等都会走fail分支并清理半成品最终返回NULL因此调用方必须判空。多线程约束在多线程序列中该函数必须以同步方式调用——克隆时输入 handle 不能正被其他线程使用。这与 easy handle 本身非线程安全的定位一致。继承规则克隆 handle 拿到什么、拿不到什么这是理解curl_easy_duphandle的核心。官方文档给出的继承语义可以归纳为两条1. 选项全部继承但指向型选项是共享指针而非拷贝。凡是此前通过curl_easy_setopt()让 handle指向某块数据而非拷贝数据的选项新 handle 也会指向同一块数据。因此你必须保证这些数据在两个 handle 都被清理之前一直存活。回调函数指针write header/data 等、CA 证书文件路径字符串指针等都属于这类共享。2. 运行时状态一律不继承。新 handle不继承任何状态信息没有已建立的连接connection pool 状态不复用没有 SSL 会话SSL session没有 cookie也不继承任何 share 对象状态或选项——克隆 handle 相当于CURLOPT_SHARE被设置为NULL的状态。从源码结构看这与 lib/easy.c 的实现完全对应新 handle 用curlx_calloc()零初始化保证无残留状态随后显式地把连接池相关状态重置outcurl-state.lastconnect_id -1; outcurl-id -1; outcurl-mid UINT32_MAX;即它从一个全新会话起步选项值则通过dupset()从源 handle 搬入。HSTS 与 alt-svc 是特例。如果源 handle 启用了 HSTS 或 alt-svc克隆 handle 会从主文件名main filename重新读取数据来填充自己的缓存对于 HSTS运行时学到的条目例如来自Strict-Transport-Security响应头也会被拷贝到克隆 handle。这一点在 lib/easy.c 中可见克隆时先Curl_hsts_init()再从STRING_HSTS指向的文件Curl_hsts_loadfile()、经Curl_hsts_loadcb()加载最后调用Curl_hsts_copy()把源 handle 内存中未过期的条目复制过来——Curl_hsts_copy()的实现位于 lib/hsts.c其注释明确写道由 curl_easy_duphandle 使用使克隆继承运行时学到的条目。alt-svc 侧则是Curl_altsvc_init()加Curl_altsvc_load()从 alt-svc 文件重建缓存lib/easy.c。源码纵深dupset() 如何逐项复制选项curl_easy_duphandle()的选项复制核心是静态函数dupset()lib/easy.c其策略可以概括为先整体拷贝结构体再处理字符串与二进制块整体结构体拷贝dst-set src-set;一行先搬走所有标量选项超时值、长整型、枚举类等字符串选项深拷贝Curl_u8_strset_copy()逐个复制 handle 中登记的字符串型选项URL、证书路径等失败即中止二进制块blob选项深拷贝遍历BLOB_LAST用Curl_setblobopt()复制 CAINFO/BLOB 类数据POST 字段副本若源 handle 有内部拷贝的 postfieldsstr_copypostfields按postfieldsize为克隆重新分配并memdupMIME 部分复制若启用 MIME/表单 API 且源 handle 有mimepostp用Curl_mime_duppart()递归克隆整个 MIME 结构。除dupset()外curl_easy_duphandle()还做了几件容易忽略的事cookie 引擎重建若源 handle 启用了 cookiedata-cookies contenteditable="false">【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表