ARTICLE DETAIL

资讯详情

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

curl 连接仅模式(CURLOPT_CONNECT_ONLY)实战指南:建立连接后接管套接字,实现自定义协议传输与 WebSocket 接管

curl 连接仅模式(CURLOPT_CONNECT_ONLY)实战指南:建立连接后接管套接字,实现自定义协议传输与 WebSocket 接管 curl 连接仅模式CURLOPT_CONNECT_ONLY实战指南建立连接后接管套接字实现自定义协议传输与 WebSocket 接管【免费下载链接】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/curlCURLOPT_CONNECT_ONLY 是 libcurl 提供的只连接、不传数据开关它让库完成 DNS 解析、TCP/TLS 握手、代理认证等全部连接准备工作后立即返回把已就绪的套接字交给应用层由应用通过 curl_easy_send / curl_easy_recv 接管后续传输。这一模式非常适合连接连通性探测、自定义协议实现以及 WebSocket 客户端改造等场景。读完本文你将掌握该选项的取值语义、与 CURLINFO_ACTIVESOCKET 的配合方式、multi 接口下的生命周期约束以及 WebSocket 模式取值 2的独特行为与底层实现依据。选项总览做什么、不做什么#include curl/curl.h CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_ONLY, long only);参数类型long即curl_easy_setopt的第三个参数。取值语义由 lib/setopt.c 的参数校验直接印证0默认值正常执行完整的数据传输流程1完成所有必需的代理认证与连接建立不进行任何数据传输随后立即返回2在 WebSocketWS/WSS协议下libcurl 会执行请求并读取完所有响应头后才把控制权交给应用程序其他协议下取值2的行为未定义。参数解析源码对取值的边界做了严格约束if(arg 0 || arg 2) result CURLE_BAD_FUNCTION_ARGUMENT;即传入负数或大于 2 的值会直接返回参数错误非法取值不会进入连接流程。在连接结构体层面该选项被拆分为两个独立标志位见 lib/urldata.hconnect_only是否执行仅连接模式connect_only_ws是否为 WebSocket 专用模式对应取值 2。选项最终被透传到连接对象上lib/url.cconn-bits.connect_only (bool)data-set.connect_only;也就是说连接层面会永久记住这是一条仅连接的连接后续复用判断、关闭策略都会围绕该标志展开。典型应用场景官方文档明确指出该选项的两大用途连接连通性测试对服务器发起一次完整的连接建立含代理、TLS 握手验证可达性后即结束不浪费带宽传数据配合CURLINFO_ACTIVESOCKET获取套接字这是最核心的用法。libcurl 完成连接后应用通过curl_easy_getinfo(handle, CURLINFO_ACTIVESOCKET, sock)拿到最近一次使用的套接字然后基于这个原始套接字做自定义的数据收发例如实现私有协议、复用已认证的连接做特殊传输。从实现角度看套接字获取的底层支撑位于 lib/connect.c 的Curl_getconnectinfo()它通过data-state.lastconnect_id定位连接并返回conn-sock[FIRSTSOCKET]。该函数注释明确写到适用于使用过 curl_easy_perform() 的 easy handle以及关联 multi handle、且连接被 CURLOPT_CONNECT_ONLY 分离的 handle与文档描述一一对应。使用示例先连接再接管官方文档给出的最小示例仅连接、不传输int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, https://example.com/); curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L); result curl_easy_perform(curl); if(result CURLE_OK) { /* only connected */ } } }在此基础上组合CURLINFO_ACTIVESOCKET与curl_easy_send/curl_easy_recv即可实现连接完成后全权接管的完整流程CURL *curl curl_easy_init(); if(curl) { curl_socket_t sockfd; char buf[4096]; size_t n; curl_easy_setopt(curl, CURLOPT_URL, https://example.com/); curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L); if(curl_easy_perform(curl) ! CURLE_OK) goto fail; /* 取出 libcurl 建立好的套接字 */ if(curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, sockfd) ! CURLE_OK) goto fail; /* 用 libcurl 的收发接口在此套接字上做自定义传输 */ curl_easy_send(curl, PING\r\n, 6, n); curl_easy_recv(curl, buf, sizeof(buf), n); ... }文档同时提醒connect-only 模式的传输不会复用任何已有连接且被标记为 connect-only 的连接也不允许被其他传输复用即连接进来、连接出去都不复用。实现上lib/conncache.c、lib/conncache.c、lib/conncache.c 等处的连接缓存逻辑均会对conn-bits.connect_only做隔离判断从连接池层面杜绝这类连接被其他请求捡走确保应用拿到的套接字状态完全可控。值 2WebSocket 专属模式从 7.86.0 起取值2在 WS/WSS 下具有明确语义libcurl 不仅建立连接还会完整发送 HTTP 升级请求并消费全部响应头确认 WebSocket 握手成功后才交还控制权。此后应用即可直接通过curl_easy_recv/curl_easy_send或curl_ws_recv/curl_ws_send在已建立的 WebSocket 连接上收发帧。底层行为差异在 lib/multi.c 有清晰的实现分界if(data-set.connect_only !data-set.connect_only_ws) { multistate(data, MSTATE_DONE); /* 普通模式连接完成即结束 */ mresult CURLM_CALL_MULTI_PERFORM; } else { /* 走 DO 阶段执行请求WebSocket 场景下读到响应头为止 */ result multi_do(data, dophase_done); }即取值1时状态机在连接完成后直接进入 DONE取值2时则继续执行协议的 DO 动作。WebSocket 实现 lib/ws.c 附近也依据data-set.connect_only分支决定握手后是进入 connect-only 挂起还是直接走回调驱动的数据循环当connect_only为真且连接已分离时会调用 lib/easy.c 的Curl_connect_only_attach()完成连接重新挂接。注意对于非 WS/WSS 协议取值2的行为未定义不应依赖。生命周期约束multi 接口下必须保持挂接文档强调了一个容易踩坑的约束如果 connect-only 传输经由 multi 接口完成该 easy handle 必须在应用继续使用期间始终保留在 multi handle 中。一旦调用curl_multi_remove_handle()将其移除curl_easy_send()和curl_easy_recv()将不再生效。原因在 lib/multi.c 的移除路径中当data-set.connect_only为真时移除 handle 会立即标记或直接关闭底层连接Curl_conn_close(data, conn, TRUE)并注释说明移除后该 easy handle 再也找不到这条连接。这与文档必须一直挂着的告诫完全一致。需要补充的细节connect-only 模式不会受CURLOPT_TIMEOUT整体超时约束。在 lib/connect.c 的超时计算中else if(!data-set.timeout || 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),仅供参考
返回列表