ARTICLE DETAIL

资讯详情

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

curl 库开发指南:CURLINFO_SIZE_DELIVERED 详解——精确统计交付给应用的回调字节数

curl 库开发指南:CURLINFO_SIZE_DELIVERED 详解——精确统计交付给应用的回调字节数 curl 库开发指南CURLINFO_SIZE_DELIVERED 详解——精确统计交付给应用的回调字节数【免费下载链接】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导读CURLINFO_SIZE_DELIVERED是 libcurl 提供的传输统计信息选项用于获取最近一次下载中实际交付给写回调write callback的字节总数。本文以 docs/libcurl/opts/CURLINFO_SIZE_DELIVERED.md 文档为主线深入其源码实现讲解该选项的语义、与CURLINFO_SIZE_DOWNLOAD_T的差异、与CURLOPT_MAXFILESIZE的协作机制并给出可直接编译运行的多场景示例。读完本文你将能准确区分下载字节数与交付字节数在启用内容解压、断点续传等场景下正确统计数据量。CURLINFO_SIZE_DELIVERED 是什么接口签名CURLINFO_SIZE_DELIVERED是一个CURLINFO_OFF_T 类型的选项通过curl_easy_getinfo读取返回 64 位宽字节计数curl_off_t#include curl/curl.h CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DELIVERED, curl_off_t *dlp);调用方式与同族的CURLINFO_SIZE_DOWNLOAD_T完全一致传入CURL*句柄、选项常量以及一个curl_off_t*指针函数将计数写入该指针。相关常量定义可参见 include/curl/curl.hCURLINFO_SIZE_DELIVERED CURLINFO_OFF_T 71。语义交付给应用的字节数按照官方文档定义该值统计的是下载过程中传递给写回调的字节总数即所谓body请求体/正文部分的实际载荷数据。以下几个关键语义需要特别注意仅统计最新一次传输该计数针对最近一次 transfer每次新传输开始时会被重置不含元数据与头部所有 meta 与 header 数据默认不纳入统计除非设置了CURLOPT_HEADER只统计交付成功的数据计数的时机是数据成功写入应用回调之后而非数据从网络上收到的瞬间。从源码看这一计数由struct Progress中的deliver字段承载定义于 lib/urldata.hcurl_off_t deliver; /* amount of data delivered to application */。每次新传输开始时该字段在Curl_pgrsReset()见 lib/progress.c中被清零void Curl_pgrsReset(struct Curl_easy *data) { Curl_pgrsSetUploadCounter(data, 0); >case CURLINFO_SIZE_DELIVERED: *param_offt >/* this counts how much data is delivered to the application, which in compressed cases may differ from downloaded amount */ void Curl_pgrs_deliver_inc(struct Curl_easy *data, size_t delta) { >while(blen !data-req.writer.paused) { if(!flush_all blen min_write) break; wlen max_write ? CURLMIN(blen, max_write) : blen; if(otype CW_OUT_BODY) result Curl_pgrs_deliver_check(data, wlen); if(!result) result cw_out_cb_write(data, wcb, wcb_data, otype, buf, wlen, nwritten); if(result) return result; if(otype CW_OUT_BODY) Curl_pgrs_deliver_inc(data, nwritten); ... }可见只有当输出类型为CW_OUT_BODY即正文数据且写入回调实际返回了nwritten字节后deliver才会累加。这从实现层面印证了文档语义交付给写回调 回调确认接收的字节数。与 CURLINFO_SIZE_DOWNLOAD_T 的区别这是使用该选项时最容易混淆的一点官方文档专门做了说明。对比维度CURLINFO_SIZE_DELIVEREDCURLINFO_SIZE_DOWNLOAD_T语义交付给写回调的字节数从网络下载的字节数计数时机数据写入回调成功之后数据接收下载时计数位置data-progress.deliverdata-progress.dl.cur_size涉及解压解压后的 body 大小原始下载大小加入版本8.20.07.55.0CURLINFO_SIZE_DOWNLOAD_T的读取实现在 lib/getinfo.c取的是data-progress.dl.cur_size而其计数更新函数Curl_pgrs_download_inc见 lib/progress.c累加的是下载增量。两者的账本不同因此在特定场景下数值会出现差异。关键差异场景启用自动解压CURLOPT_ACCEPT_ENCODING当通过CURLOPT_ACCEPT_ENCODING启用自动解压如gzip、deflate、br、zstd等时CURLINFO_SIZE_DELIVERED返回的是解压后的 body 大小——因为应用回调收到的就是解压后的数据CURLINFO_SIZE_DOWNLOAD_T返回的是压缩后的原始下载大小——因为线上传输的字节数并未改变。举例服务器返回 10 MB 的 HTML 文档gzip 压缩后线上只传输了 2 MB。那么CURLINFO_SIZE_DOWNLOAD_T约为 2 MB而CURLINFO_SIZE_DELIVERED约为 10 MB。这一设计让开发者可以同时获知网络流量与应用数据处理量两个指标。其他辅助对比选项CURLINFO_SIZE_UPLOAD_T上传方向的对应统计lib/getinfo.cCURLINFO_CONTENT_LENGTH_DOWNLOAD_T服务器声明的下载内容长度已知时未知时返回 -1lib/getinfo.c旧的CURLINFO_SIZE_DOWNLOAD非_T后缀已被标记为废弃CURL_DEPRECATED(7.55.0, ...)见 include/curl/curl.h新代码应使用_T版本。与 CURLOPT_MAXFILESIZE 的协作机制CURLINFO_SIZE_DELIVERED并非孤立存在——它在内部还参与了CURLOPT_MAXFILESIZE最大文件大小限制的判定。在 lib/progress.c 中定义了交付前的预检查/* check that the delta amount of bytes are okay to deliver to the application, or return error if not. */ CURLcode Curl_pgrs_deliver_check(struct Curl_easy *data, size_t delta) { if(data-set.max_filesize ((curl_off_t)delta >int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); /* Perform the request */ result curl_easy_perform(curl); if(result CURLE_OK) { /* check the size */ curl_off_t dl; result curl_easy_getinfo(curl, CURLINFO_SIZE_DELIVERED, dl); if(result CURLE_OK) { printf(Stored % CURL_FORMAT_CURL_OFF_T bytes\n, dl); } } } }要点说明打印curl_off_t时必须使用宏CURL_FORMAT_CURL_OFF_T作为格式化占位符以保证在 32/64 位平台上格式串正确curl_easy_getinfo返回CURLE_OK (0)表示成功非零表示出错具体错误码可参考 libcurl 的错误文档libcurl-errors。进阶示例对比解压前后的两个数值为了直观验证解压后交付量 ≠ 原始下载量可以同时读取两个选项做对比#include stdio.h #include curl/curl.h int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_off_t delivered 0, downloaded 0; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); /* 请求 gzip 压缩响应并让 libcurl 自动解压 */ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, gzip, deflate, br, zstd); result curl_easy_perform(curl); if(result CURLE_OK) { curl_easy_getinfo(curl, CURLINFO_SIZE_DELIVERED, delivered); curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, downloaded); printf(delivered: % CURL_FORMAT_CURL_OFF_T bytes\n, delivered); printf(downloaded: % CURL_FORMAT_CURL_OFF_T bytes\n, downloaded); if(delivered downloaded) printf(响应经过压缩传输解压后多出 % CURL_FORMAT_CURL_OFF_T bytes\n, delivered - downloaded); } curl_easy_cleanup(curl); } return 0; }如果目标服务器支持内容压缩delivered通常大于downloaded如果服务器返回未压缩内容两者通常相等。注意CURLINFO_SIZE_DOWNLOAD_T在文档中标注支持的协议为 All所有协议而CURLINFO_SIZE_DELIVERED同样适用于全部协议Protocol: All两个选项均可放心用于通用下载统计。使用注意事项结合文档与源码实现使用时有以下几点值得留意计数针对单次传输若句柄被复用于多次curl_easy_perform或 multi 接口中的多次 transfer每次新传输开始都会将deliver重置为 0见Curl_pgrsReset。因此应在每次传输完成后立即读取不要期望它跨传输累计。头数据默认不计入CURLINFO_SIZE_DELIVERED默认统计的是 body 部分只有显式设置CURLOPT_HEADER时头部数据才会计入交付量。需要单独统计头部字节时应结合写回调自行累加。解压场景的语义差异启用CURLOPT_ACCEPT_ENCODING后该值与CURLINFO_SIZE_DOWNLOAD_T的差异是正常且符合设计的不要将其当作统计 bug两者分别回答应用处理了多少数据与网络传输了多少数据。与进度条/上传选项的关系CURLINFO_SIZE_DELIVERED仅反映下载交付方向上传方向请使用CURLINFO_SIZE_UPLOAD_T。另外CURLINFO_SIZE_DELIVERED加入于8.20.0版本见文档头部Added-in: 8.20.0如果你的环境版本较旧需要先确认 libcurl 是否支持该选项或改用CURLINFO_SIZE_DOWNLOAD_T作为降级方案。相关文档与源码索引官方选项文档docs/libcurl/opts/CURLINFO_SIZE_DELIVERED.md同族选项docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md、docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md、docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md选项枚举定义include/curl/curl.h读取实现lib/getinfo.c计数与重置实现lib/progress.c、lib/progress.c计数触发点写回调输出管道lib/cw-out.c内部数据结构lib/urldata.h配套选项文档docs/libcurl/opts/CURLOPT_MAXFILESIZE.md、docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md、docs/libcurl/opts/curl_easy_getinfo.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),仅供参考
返回列表