ARTICLE DETAIL

资讯详情

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

libcurl CURLINFO_ACTIVESOCKET:获取 curl_easy_getinfo 返回的当前活动套接字

libcurl CURLINFO_ACTIVESOCKET:获取 curl_easy_getinfo 返回的当前活动套接字 libcurl CURLINFO_ACTIVESOCKET获取 curl_easy_getinfo 返回的当前活动套接字【免费下载链接】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 仓库官方手册 CURLINFO_ACTIVESOCKET 展开系统讲解curl_easy_getinfo的CURLINFO_ACTIVESOCKET选项它如何把 libcurl 建立连接后使用的最近一个活动套接字交给应用层为什么它与CURLOPT_CONNECT_ONLY天然成对出现以及它在源码层面如何通过Curl_getconnectinfo()定位到实际 socket。读完本文你将能够正确编写连接即接管的自定义传输代码如配合curl_easy_send/curl_easy_recv或 WebSocket 使用并理解该 API 取代已弃用的CURLINFO_LASTSOCKET的原因。选项概览与基本信息CURLINFO_ACTIVESOCKET是curl_easy_getinfo(3)的一个查询选项CURLINFO 系列其核心功能是向 libcurl 索要本 easy handle 最近一次传输连接所使用的活动套接字。项目内容选项名CURLINFO_ACTIVESOCKET使用接口curl_easy_getinfo返回值类型curl_socket_t *无效时的返回值CURL_SOCKET_BAD支持协议全部All引入版本libcurl 7.45.0常配套使用的选项CURLOPT_CONNECT_ONLY取代的选项CURLINFO_LASTSOCKET自 7.45.0 起弃用该枚举定义位于公开头文件 curl.h其中CURLINFO_ACTIVESOCKET的取值为CURLINFO_SOCKET 44见 curl.h 第 2996 行附近被其取代的CURLINFO_LASTSOCKET则带有弃用标注curl.h 第 2979 行。SYNOPSIS函数原型#include curl/curl.h CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET, curl_socket_t *socket);要点说明第三个参数必须是一个curl_socket_t类型变量的指针libcurl 会把 socket 描述符写入该地址curl_socket_t是 libcurl 对平台 socket 类型的抽象POSIX 下即文件描述符Windows 下为SOCKET这正是它比旧选项CURLINFO_LASTSOCKET写入long *更可靠的根本原因——详见后文为什么弃用 LASTSOCKET一节该调用本身返回CURLcodeCURLE_OK (0)表示查询成功非零表示出错参见 libcurl-errors 相关说明即手册中的 libcurl-errors(3)。DESCRIPTION语义、生命周期与使用前提官方文档的完整语义可归纳为以下三条每一条都直接影响你的写法1. 返回最近一次活动的 socket无效时为CURL_SOCKET_BAD。libcurl 会为一次传输选择某个连接并持有对应的 socketCURLINFO_ACTIVESOCKET取回的就是本次会话最近一次传输连接所使用的 socket。如果当前没有有效 socket例如传输尚未建立连接、连接已失效则写入CURL_SOCKET_BAD。因此拿到结果后必须显式检查该哨兵值。2. 套接字的生命周期仍归 libcurl 所有。文档明确要求当你用完这个 socket 后仍需像往常一样对该 easy handle 调用curl_easy_cleanup(3)由 libcurl 负责关闭 socket 并清理 handle 关联的其他资源。换言之curl_easy_cleanup之后不得再使用该 socket 值在 cleanup 之前应用层也不应自行close()该 socket在CURLOPT_CONNECT_ONLY接管模式下尤其如此——此时该 socket 正是应用自己的数据通道。3. 仅在传输完成后返回活动 socket典型搭配CURLOPT_CONNECT_ONLY。原文强调This option returns the active socket only after the transfer is complete, and is typically used in combination with CURLOPT_CONNECT_ONLY(3), which skips the transfer phase.该选项仅在传输完成后返回活动 socket通常与跳过传输阶段的CURLOPT_CONNECT_ONLY配合使用。这里的transfer是指 libcurl 替你发起并管理的那次传输。当设置CURLOPT_CONNECT_ONLY时curl_easy_perform会完成全部代理认证与连接建立含 TLS 握手等但不做数据收发即返回此时 socket 被移交给应用层CURLINFO_ACTIVESOCKET成为拿到它句柄的标准方式。配套的 CURLOPT_CONNECT_ONLY 手册还给出了几条必须注意的规则可传1完成代理认证与连接建立后返回不做传输可传2若使用 WebSocketlibcurl 会先完成握手请求并读完全部响应头再移交控制权其他协议下该取值的含义未定义标记为 connect-only 的传输不复用已有连接其建立的连接也不允许被复用若通过 multi 接口执行 connect-only 传输该 easy handle 必须持续保留在 multi handle 中一旦执行curl_multi_remove_handlecurl_easy_send/curl_easy_recv即不再可用。默认值为0不启用。完整示例连接即接管以下代码完整继承自官方文档的 EXAMPLE 部分展示只连接、不传输然后提取 socket的标准流程int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_socket_t sockfd; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); /* Do not do the transfer - only connect to host */ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L); result curl_easy_perform(curl); if(result ! CURLE_OK) { printf(Error: %s\n, curl_easy_strerror(result)); curl_easy_cleanup(curl); return 1; } /* Extract the socket from the curl handle */ result curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, sockfd); if(!result sockfd ! CURL_SOCKET_BAD) { /* operate on sockfd */ } curl_easy_cleanup(curl); } }逐行要点curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L)告诉 libcurl 只做连接。对于https://URLcurl_easy_perform返回时 TCP 连接与 TLS 握手均已完成但没有发送任何 HTTP 请求。curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, sockfd)取出该 socket。注意两层判断——getinfo的CURLcode成功且sockfd ! CURL_SOCKET_BAD。拿到sockfd后即可按平台 API 直接读写例如在 TLS 之上的裸 socket 上实现自定义协议。仓库中还有一个完整的取 socket 后用curl_easy_send/curl_easy_recv收发的示例 sendrecv.c它演示了接管 socket 后继续用 libcurl 封装接口收发数据的方式同样依赖CURLOPT_CONNECT_ONLY。最后curl_easy_cleanup(curl)统一收尾由 libcurl 关闭 socket。源码级实现解析ACTIVESOCKET 是如何取回的结合仓库源码可以看清该选项的完整调用链这有助于解释上述文档中仅在传输完成后有效的原因。第一环getinfo 分发。在 lib/getinfo.c 中Curl_getinfo对 socket 类选项调用专门的getinfo_socket辅助函数static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info, curl_socket_t *param_socketp) { switch(info) { case CURLINFO_ACTIVESOCKET: *param_socketp Curl_getconnectinfo(data, NULL); break; default: return CURLE_UNKNOWN_OPTION; } return CURLE_OK; }参见 lib/getinfo.c 第 601-613 行。可以看到CURLINFO_ACTIVESOCKET的处理就是一行调用Curl_getconnectinfo(data, NULL)并写入结果。第二环从连接池定位最近一次传输的连接。Curl_getconnectinfo实现在 lib/connect.c第 182 行附近curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, struct connectdata **connp) { ... if(data-state.lastconnect_id ! -1) { struct connectdata *conn; conn Curl_cpool_get_conn(data,>CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LASTSOCKET, long *socket);问题在于long在 64 位 Windowswin64上是 32 位而SOCKET类型是 64 位的用一个 32 位的long传递 socket 会截断句柄、导致不可靠——该手册明确标注 this API is deprecated since it is not working on win64 where the SOCKET type is 64 bits large while its long is 32 bits。因此 libcurl 在 7.45.0 引入CURLINFO_ACTIVESOCKET改用平台感知的curl_socket_t类型作为接收参数CURLINFO_ACTIVESOCKET手册也写明CURLINFO_ACTIVESOCKET(3) was added as a replacement for CURLINFO_LASTSOCKET(3) since that one is not working on all platforms.CURLINFO_ACTIVESOCKET是作为CURLINFO_LASTSOCKET的替代品加入的因为后者并非在所有平台上都可用。两者行为约定几乎一致无效时旧版返回-1、新版返回CURL_SOCKET_BAD都要求最终curl_easy_cleanup都典型搭配CURLOPT_CONNECT_ONLY新代码应一律使用CURLINFO_ACTIVESOCKET。测试用例印证仓库的 lib 测试套件为该选项提供了可复现的行为验证测试程序 tests/libtest/lib677.c 即 test677 的可执行体验证CURLOPT_CONNECT_ONLYCURLINFO_ACTIVESOCKET的组合行为对应的测试定义文件为 tests/data/test677可通过仓库的测试框架tests/runtests.pl等运行以观察预期输出。这组测试为connect-only 后能取到有效 socket这一核心契约提供了回归保障。RETURN VALUE 与返回码curl_easy_getinfo(3)返回CURLcode表示成功或错误CURLE_OK (0)一切正常socket 值可能是有效的 socket 句柄也可能是CURL_SOCKET_BAD已写入参数指向的位置非零值查询本身出错例如 handle 无效、选项参数缺失等具体错误含义参见 libcurl-errors(3)。一个常见的辨析点CURLcode成功不代表socket 一定有效——CURLE_OK时仍需检查sockfd ! CURL_SOCKET_BAD这两层检查缺一不可。关联文档索引CURLOPT_CONNECT_ONLY使curl_easy_perform只建立连接而不传输本选项最典型的搭档CURLINFO_LASTSOCKET被CURLINFO_ACTIVESOCKET取代的旧选项7.45.0 起弃用win64 上不可靠curl_easy_getinfo本选项所属的查询接口curl_easy_setopt设置CURLOPT_CONNECT_ONLY等选项的接口curl_easy_send / curl_easy_recv在 connect-only 接管的连接上直接收发的配套 API另见 sendrecv 示例。【免费下载链接】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),仅供参考
返回列表