新闻详情

新闻详情

首页 / 资讯中心 / 详情

libcurl CURLMINFO_XFERS_DONE 详解:查询已完成但未取回的 multi 传输数量

发布时间:2026/9/10 5:05:27来源:尧图网络
libcurl CURLMINFO_XFERS_DONE 详解:查询已完成但未取回的 multi 传输数量
libcurl CURLMINFO_XFERS_DONE 详解查询已完成但未取回的 multi 传输数量【免费下载链接】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本篇技术指南深入讲解 curl 项目 libcurl 多接口multi interface提供的CURLMINFO_XFERS_DONE信息选项说明它如何精确回答有多少个 easy handle 已经结束传输、但其完成消息尚未被应用通过curl_multi_info_read取走这一并发调度核心问题。读完本文你将掌握curl_multi_get_offt的调用方式、CURLMINFO_XFERS_DONE与同族计数器CURRENT / RUNNING / PENDING / ADDED的区别以及如何基于该指标编写健壮的多传输完成轮询与消息消费代码。一、背景multi 接口中的传输状态机libcurl 的 multi 接口允许应用在单个线程内同时管理多个 easy handle传输。每个被curl_multi_add_handle加入的传输在 multi 内部会经历若干状态等待启动pending、正在处理process/running、已完成但消息未读msgsent、以及被应用取走消息并移除。当前 curl 源码使用一组uint32_bset无符号 32 位位集合来跟踪这些状态定义于 lib/multihandle.hstruct uint32_bset process; /* transfer being processed */ struct uint32_bset pending; /* transfers in waiting (conn limit etc.) */ struct uint32_bset msgsent; /* transfers with unread application messages */CURLMINFO_XFERS_DONE正是对msgsent集合元素个数的对外暴露它统计的是传输已经结束、但完成消息还堆在 multi 内部队列里等待应用读取的 easy handle 数量。二、接口签名与调用方式CURLMINFO_XFERS_DONE属于CURLMinfo_offt枚举见 include/curl/multi.h必须通过curl_multi_get_offt读取函数原型如下#include curl/curl.h CURLMcode curl_multi_get_offt(CURLM *handle, CURLMINFO_XFERS_DONE, curl_off_t *pvalue);参数说明参数含义handle已由curl_multi_init创建、且仍有效的 multi 句柄info要查询的信息项此处为CURLMINFO_XFERS_DONEpvalue指向curl_off_t的输出指针调用成功后写入统计值对应的最小示例来自官方文档int main(void) { CURLM *m curl_multi_init(); curl_off_t value; curl_multi_get_offt(m, CURLMINFO_XFERS_DONE, value); }三、语义精解finished 但未被 processed官方文档对CURLMINFO_XFERS_DONE的定义是The number of easy handles currently finished, but not yet processed via curl_multi_info_read(3).拆解这句话包含两层含义finished已结束该 easy handle 对应的传输已经跑完——无论成功还是出错——CURLMSG_DONE消息已经生成not yet processed尚未取走应用还没有通过curl_multi_info_read把这条完成消息从内部队列中读出。因此这个数字衡量的是完成消息积压量。它在两种典型场景下很有价值批量下载/上传完成监控当XFERS_DONE 0时说明有传输已结束应立即调用curl_multi_info_read消费消息、清理句柄避免句柄与内存滞留调度器空闲判断若XFERS_DONE与CURLMINFO_XFERS_RUNNING同时为 0 且还有待启动的传输CURLMINFO_XFERS_PENDING 0可据此推断调度瓶颈。从源码结构看lib/multi.c其实现正是直接返回msgsent位集合的元素个数case CURLMINFO_XFERS_DONE: *pvalue (curl_off_t)Curl_uint32_bset_count(multi-msgsent); break;四、源码级联动消息是如何进入与离开 msgsent 的要真正理解XFERS_DONE需要看清msgsent集合在 libcurl 内部的两个关键动作点。4.1 进入multi_addmsg 标记消息未读当一个传输完成时libcurl 调用内部函数multi_addmsg把该 easy handle 的mid加入msgsent集合并触发一次通知lib/multi.cstatic void multi_addmsg(struct Curl_multi *multi, struct Curl_easy *data) { if(Curl_uint32_bset_empty(multi-msgsent)) CURLM_NTFY(multi-admin, CURLMNOTIFY_INFO_READ); Curl_uint32_bset_add(multi-msgsent,>CURLMsg *curl_multi_info_read(CURLM *m, int *msgs_in_queue) { ... if(Curl_uint32_bset_first(multi-msgsent, mid)) { struct Curl_easy *data Curl_multi_get_easy(multi, mid); Curl_uint32_bset_remove(multi-msgsent, mid); *msgs_in_queue curlx_uztosi(Curl_uint32_bset_count(multi-msgsent)); if(data) msg_result data-msg; } ... }由此可以清晰验证一个等式curl_multi_get_offt(m, CURLMINFO_XFERS_DONE, n)的值与调用curl_multi_info_read返回的第二个参数*msgs_in_queue本次读取后剩余队列长度在语义上指向同一个msgsent集合。两条 API 互为表里XFERS_DONE告诉你还有几条没读msgs_in_queue告诉你读完这条还剩几条。实践中XFERS_DONE 0意味着完成队列已被清空可以安全地继续调度新任务。4.3 生命周期与清理msgsent集合在 multi 句柄创建时初始化lib/multi.c在句柄销毁时释放easy handle 被curl_multi_remove_handle移除时也会从该集合中清除对应midlib/multi.c。因此XFERS_DONE始终反映的是当前仍由该 multi 管理、且消息未读的传输数不包含已移除的句柄。五、与同族 CURLMINFO_XFERS_* 计数器的完整对比CURLMINFO_XFERS_DONE不是孤立存在的它与另外四个枚举项共同刻画 multi 内部传输的完整生命周期。五个枚举定义于 include/curl/multi.htypedef enum { CURLMINFO_NONE, /* first, never use this */ /* The number of easy handles currently managed by the multi handle, * e.g. have been added but not yet removed. */ CURLMINFO_XFERS_CURRENT 1, /* The number of easy handles running, e.g. not done and not queueing. */ CURLMINFO_XFERS_RUNNING 2, /* The number of easy handles waiting to start, e.g. for a connection * to become available due to limits on parallelism, max connections * or other factors. */ CURLMINFO_XFERS_PENDING 3, /* The number of easy handles finished, waiting for their results to * be read via curl_multi_info_read(). */ CURLMINFO_XFERS_DONE 4, /* The total number of easy handles added to the multi handle, ever. */ CURLMINFO_XFERS_ADDED 5, CURLMINFO_LASTENTRY /* the last unused */ } CURLMinfo_offt;对应关系可总结为下表枚举项语义底层集合说明文档CURLMINFO_XFERS_CURRENT当前已加入、尚未移除的 easy handle 总数含内部句柄如 DoH 解析任务multi-xfers表CURLMINFO_XFERS_CURRENTCURLMINFO_XFERS_RUNNING正在运行、既未完成也未排队的传输数multi-processCURLMINFO_XFERS_RUNNINGCURLMINFO_XFERS_PENDING等待启动的传输数受连接数上限、DNS 解析未完成、等待判定是否可复用连接做 HTTP/2 或 HTTP/3 多路复用等影响multi-pendingCURLMINFO_XFERS_PENDINGCURLMINFO_XFERS_DONE已完成、但消息尚未被curl_multi_info_read取走的传输数multi-msgsentCURLMINFO_XFERS_DONECURLMINFO_XFERS_ADDED从 multi 句柄创建以来累计加入的传输总数只增不减用于统计吞吐multi-xfers_total_everCURLMINFO_XFERS_ADDED在任意稳定时刻近似满足CURRENT ≈ RUNNING PENDING DONE因为CURRENT还会计入尚未进入上述三个状态或正处于状态迁移中的传输以及内部句柄。这五个指标组合起来可以完整刻画一个 multi 调度器的实时负载。XFERS_PENDING的官方文档还专门解释了等待启动的成因——连接数限制、DNS 解析未完成、以及不确定已有连接是否允许 HTTP/2/HTTP/3 多路复用这些都可能让一个已加入的传输进入 pending 状态详见 CURLMINFO_XFERS_PENDING。六、实战完成监控与消息消费的完整循环下面的示例展示了CURLMINFO_XFERS_DONE在真实事件循环中的用法向 multi 添加多个 easy handle周期性地驱动curl_multi_perform并在发现XFERS_DONE 0时立即消费全部完成消息、取出每个传输的结果码并清理句柄。#include stdio.h #include curl/curl.h int main(void) { CURLM *multi curl_multi_init(); CURL *easy[3]; curl_off_t done; int still_running 0; int i; /* 1. 创建并添加多个 easy handle */ for(i 0; i 3; i) { easy[i] curl_easy_init(); curl_easy_setopt(easy[i], CURLOPT_URL, https://example.com/); curl_multi_add_handle(multi, easy[i]); } /* 2. 驱动传输直到没有正在运行的传输且完成队列为空 */ do { CURLMcode mc curl_multi_perform(multi, still_running); if(mc ! CURLM_OK) break; /* 3. 查询已完成但未读取消息的传输数 */ mc curl_multi_get_offt(multi, CURLMINFO_XFERS_DONE, done); if(mc ! CURLM_OK) break; /* 4. 有完成消息就全部消费掉 */ if(done 0) { struct CURLMsg *m; do { int msgq 0; m curl_multi_info_read(multi, msgq); if(m (m-msg CURLMSG_DONE)) { CURL *e m-easy_handle; printf(transfer finished, result%d\n, m-data.result); curl_multi_remove_handle(multi, e); curl_easy_cleanup(e); } } while(m); } if(still_running) curl_multi_poll(multi, NULL, 0, 1000, NULL); } while(still_running 0); curl_multi_cleanup(multi); return 0; }要点说明每轮循环先curl_multi_perform推进传输再用CURLMINFO_XFERS_DONE判断是否有积压的完成消息curl_multi_info_read返回的CURLMsg中msg CURLMSG_DONE表示传输结束data.result是该传输的返回码CURLcode读取到消息后应立即curl_multi_remove_handle并curl_easy_cleanup防止句柄泄漏官方文档明确警告curl_multi_info_read返回的指针在调用curl_multi_cleanup、curl_multi_remove_handle或curl_easy_cleanup后即失效不能跨调用保存详见 curl_multi_info_read退出条件是still_running 0此时若再查一次XFERS_DONE应为 0或残余消息被立即读空可作为循环结束的二次校验。七、返回值与错误处理curl_multi_get_offt返回CURLMcodeCURLM_OK0查询成功*pvalue已写入有效统计值非零值查询出错需要查阅 libcurl-errors 定位具体错误码。从实现看lib/multi.c有两个值得注意的错误分支CURLM_BAD_FUNCTION_ARGUMENT当pvalue为NULL空指针时返回因此调用前务必保证输出指针有效CURLM_UNKNOWN_OPTION当info不是合法的CURLMinfo_offt枚举值时返回此时*pvalue会被写入-1以作标记。另外curl_multi_get_offt的实现整体位于CURL_MAPI_ENTER/CURL_MAPI_LEAVE保护的临界区内并返回CURLMcode mresult若进入失败例如句柄无效也会以错误码形式上报而不是直接崩溃。八、可用性与版本说明CURLMINFO_XFERS_DONE及其同族的CURLMINFO_XFERS_CURRENT、CURLMINFO_XFERS_RUNNING、CURLMINFO_XFERS_PENDING、CURLMINFO_XFERS_ADDED以及配套的读取函数curl_multi_get_offt均在libcurl 8.16.0版本新增见 curl_multi_get_offt 与本文档的Added-in元数据。在使用前需确认链接的 libcurl 版本不低于 8.16.0或在编译期通过LIBCURL_VERSION_NUM做版本判断#if LIBCURL_VERSION_NUM 0x081000 /* 8.16.0 */ curl_multi_get_offt(m, CURLMINFO_XFERS_DONE, n); #endif该选项适用于所有协议Protocol: All不依赖任何特定传输类型。CURLMINFO_XFERS_DONE没有默认值概念文档标注 n/a它始终返回当前实时统计值仅在curl_multi_get_offt返回CURLM_OK时才有意义。九、小结CURLMINFO_XFERS_DONE是 libcurl multi 接口为应用提供的完成消息积压量探针它直接映射到内部msgsent位集合与curl_multi_info_read的消费动作一一对应。在实战中将它与CURLMINFO_XFERS_CURRENT、CURLMINFO_XFERS_RUNNING、CURLMINFO_XFERS_PENDING组合使用可以完整掌握 multi 调度器在任何时刻的负载分布从而写出更健壮的批量传输、连接池调度与完成回收逻辑。相关接口的权威定义与配套用法可在仓库的 include/curl/multi.h、lib/multi.c 与 docs/libcurl/curl_multi_get_offt.md 中进一步查阅。【免费下载链接】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),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

基于 ASCII 走私的金融钓鱼邮件规避技术与防御研究 2026/9/10 5:47:33

基于 ASCII 走私的金融钓鱼邮件规避技术与防御研究

摘要网络钓鱼攻击的对抗重心正从表层文本伪装向底层字符编码空间迁移。微软安全团队在针对人工智能提示注入开展威胁狩猎过程中,意外发现 ASCII 走私技术已被黑产迁移至传统金融钓鱼邮件场景,利用 Unicode 标签区块内不可见镜像字符割裂 "funding&q…

阅读更多 →
ECC 规则体系实战:为 Claude Code 配置 PHP 专属 Hooks,实现自动格式化、静态分析与安全告警 2026/9/10 5:47:33

ECC 规则体系实战:为 Claude Code 配置 PHP 专属 Hooks,实现自动格式化、静态分析与安全告警

ECC 规则体系实战:为 Claude Code 配置 PHP 专属 Hooks,实现自动格式化、静态分析与安全告警 【免费下载链接】ECC The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Clau…

阅读更多 →
C++ OpenCV二维码识别实战:高鲁棒性工业级部署方案 2026/9/10 5:47:33

C++ OpenCV二维码识别实战:高鲁棒性工业级部署方案

简介:本资源是一套基于C与OpenCV实现的二维码识别算法实战项目,面向具备基础C编程能力和图像处理认知的中级开发者,解决实际场景中二维码鲁棒识别、快速解码与工程化部署等核心问题。压缩包共10个文件,含2个核心CPP源码&#xff0…

阅读更多 →
DeepSeek Harness实测:插件化架构如何重塑AI工具生态 2026/9/10 5:47:33

DeepSeek Harness实测:插件化架构如何重塑AI工具生态

最近几天打开技术社区,满屏都是 DeepSeek Harness 的讨论。有人把它捧成"AI 时代的 Chrome",也有人泼冷水说不过是又一轮插件生态圈地。作为一个从命令行时代就开始折腾各种工具链的老玩家,我花了整整一个周末把 Harness 从安装到深…

阅读更多 →
迁移学习实战:用Transformers库微调BERT与LoRA 2026/9/10 5:47:33

迁移学习实战:用Transformers库微调BERT与LoRA

我在刚接触NLP那会儿,总以为训练一个模型就得从零开始,把整套网络结构重新设计一遍。直到有一次接到一个文本分类需求,前辈丢给我一句“用BERT微调一下就行”,我才真正理解什么叫迁移学习。现在无论你看哪篇大模型实战文章&#x…

阅读更多 →
DeepTutor v1.2.1 版本深度解析:Chat 分阶段 Token 配额可配置化与 Regenerate 响应再生成机制 2026/9/10 5:44:32

DeepTutor v1.2.1 版本深度解析:Chat 分阶段 Token 配额可配置化与 Regenerate 响应再生成机制

DeepTutor v1.2.1 版本深度解析:Chat 分阶段 Token 配额可配置化与 Regenerate 响应再生成机制 【免费下载链接】DeepTutor DeepTutor: Lifelong Personalized Tutoring. https://deeptutor.info/. 项目地址: https://gitcode.com/GitHub_Trending/dee/DeepTutor …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞