掌握libcurl:从GET请求到HTTPS验证全解析
1. 初始化 libcurl在程序开始时调用一次#includestdio.h#includecurl/curl.hintmain(void){CURLcode res;rescurl_global_init(CURL_GLOBAL_DEFAULT);if(res!CURLE_OK){fprintf(stderr,curl_global_init failed: %s\n,curl_easy_strerror(res));return1;}// 后续执行网络请求curl_global_cleanup();return0;}注意curl_global_init()通常只需要调用一次。curl_global_cleanup()应该在程序结束时调用。如果程序中有多个CURL *对象也不应该重复调用全局初始化和清理函数。2. 创建 CURL 对象CURL*curlcurl_easy_init();if(curlNULL){fprintf(stderr,curl_easy_init failed\n);curl_global_cleanup();return1;}curl_easy_init()用于创建一个 easy handle也就是一次请求的控制对象。使用完成后必须调用curl_easy_cleanup(curl);3. 设置请求 URLconstchar*urlhttps://example.com;CURLcode rescurl_easy_setopt(curl,CURLOPT_URL,url);if(res!CURLE_OK){fprintf(stderr,CURLOPT_URL failed: %s\n,curl_easy_strerror(res));}也可以直接写成curl_easy_setopt(curl,CURLOPT_URL,https://example.com);curl_easy_setopt 的返回值curl_easy_setopt的函数形式是CURLcodecurl_easy_setopt(CURL*handle,CURLoption option,...);它返回一个CURLcode用于表示设置是否成功。常见的错误检查方式#defineCHECK_CURL(expr)\do{\CURLcode code(expr);\if(code!CURLE_OK){\fprintf(stderr,%s failed: %s\n,\#expr,curl_easy_strerror(code));\}\}while(0)4. 设置响应数据的处理函数libcurl 接收到服务器响应数据后会调用回调函数。回调函数原型为size_twrite_callback(char*ptr,size_tsize,size_tnmemb,void*userdata);参数说明参数含义ptr接收到的数据size每个数据单元的大小nmemb数据单元数量userdata用户自定义参数返回值实际处理的数据字节数实际数据长度为size * nmemb重要注意ptr指向的数据不一定以\0结尾不能直接当作 C 字符串使用可能包含二进制数据回调函数返回值必须表示已经处理的字节数。5. 将响应数据写入文件下面的回调函数可以将数据写入文件#includestdio.hsize_twrite_callback(char*ptr,size_tsize,size_tnmemb,void*userdata){FILE*fp(FILE*)userdata;returnfwrite(ptr,size,nmemb,fp)*size;}设置回调函数FILE*fpfopen(response.html,wb);if(fpNULL){perror(fopen);curl_easy_cleanup(curl);curl_global_cleanup();return1;}curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_callback);curl_easy_setopt(curl,CURLOPT_WRITEDATA,fp);这里CURLOPT_WRITEFUNCTION用于设置响应数据回调函数CURLOPT_WRITEDATA用于设置传递给回调函数的 userdata 参数。因此下面两项是配套使用的curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_callback);curl_easy_setopt(curl,CURLOPT_WRITEDATA,fp);回调函数被调用时userdata fp6. 将响应数据直接输出到标准输出如果想把服务器响应直接打印到终端curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_callback);curl_easy_setopt(curl,CURLOPT_WRITEDATA,stdout);也可以不设置CURLOPT_WRITEFUNCTIONlibcurl 默认会把响应写到标准输出。但显式设置更容易理解和控制。7. 执行网络请求CURLcode rescurl_easy_perform(curl);if(res!CURLE_OK){fprintf(stderr,curl_easy_perform failed: %s\n,curl_easy_strerror(res));}curl_easy_perform()会同步执行请求函数调用期间会阻塞当前线程接收到响应数据时会调用CURLOPT_WRITEFUNCTION设置的回调函数请求完成后才会返回。常见错误码错误码含义CURLE_OK操作成功CURLE_UNSUPPORTED_PROTOCOL不支持的协议CURLE_COULDNT_CONNECT无法连接服务器CURLE_OPERATION_TIMEDOUT请求超时CURLE_HTTP_RETURNED_ERRORHTTP 错误通常需要配合选项CURLE_SSL_CONNECT_ERRORSSL 连接错误8. 设置常用选项设置超时时间curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,10L);curl_easy_setopt(curl,CURLOPT_TIMEOUT,30L);含义CURLOPT_CONNECTTIMEOUT连接服务器的最长时间CURLOPT_TIMEOUT整个请求允许的最长时间。跟随重定向服务器可能返回 301 或 302 重定向可以开启自动跟随curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L);设置 User-Agentcurl_easy_setopt(curl,CURLOPT_USERAGENT,my-curl-client/1.0);设置 HTTPS 证书验证libcurl 默认会验证 HTTPS 证书建议保持默认配置curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1L);curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,2L);不建议在生产环境中使用CURLOPT_SSL_VERIFYPEER0CURLOPT_SSL_VERIFYHOST0关闭验证会降低 HTTPS 的安全性只适合临时测试。9. 获取 HTTP 状态码curl_easy_perform()成功只代表网络层请求成功不一定代表 HTTP 返回码是 200。例如服务器可能返回200成功404资源不存在500服务器错误可以通过curl_easy_getinfo()获取 HTTP 状态码longresponse_code0;rescurl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,response_code);if(resCURLE_OK){printf(HTTP response code: %ld\n,response_code);}10. 一个完整的 GET 请求示例#includestdio.h#includecurl/curl.hstaticsize_twrite_callback(char*ptr,size_tsize,size_tnmemb,void*userdata){FILE*fp(FILE*)userdata;/* ptr 不一定是以 \0 结尾的字符串 必须按照 size 和 nmemb 指定的长度处理。 */returnfwrite(ptr,size,nmemb,fp)*size;}intmain(void){CURL*curlNULL;CURLcode res;longresponse_code0;rescurl_global_init(CURL_GLOBAL_DEFAULT);if(res!CURLE_OK){fprintf(stderr,curl_global_init failed: %s\n,curl_easy_strerror(res));return1;}curlcurl_easy_init();if(curlNULL){fprintf(stderr,curl_easy_init failed\n);curl_global_cleanup();return1;}FILE*fpfopen(response.html,wb);if(fpNULL){perror(fopen);curl_easy_cleanup(curl);curl_global_cleanup();return1;}rescurl_easy_setopt(curl,CURLOPT_URL,https://example.com);if(res!CURLE_OK){fprintf(stderr,set URL failed: %s\n,curl_easy_strerror(res));gotocleanup;}rescurl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_callback);if(res!CURLE_OK){fprintf(stderr,set write callback failed: %s\n,curl_easy_strerror(res));gotocleanup;}rescurl_easy_setopt(curl,CURLOPT_WRITEDATA,fp);if(res!CURLE_OK){fprintf(stderr,set write data failed: %s\n,curl_easy_strerror(res));gotocleanup;}curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L);curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,10L);curl_easy_setopt(curl,CURLOPT_TIMEOUT,30L);curl_easy_setopt(curl,CURLOPT_USERAGENT,my-curl-client/1.0);rescurl_easy_perform(curl);if(res!CURLE_OK){fprintf(stderr,request failed: %s\n,curl_easy_strerror(res));gotocleanup;}rescurl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,response_code);if(resCURLE_OK){printf(HTTP response code: %ld\n,response_code);}cleanup:fclose(fp);curl_easy_cleanup(curl);curl_global_cleanup();returnresCURLE_OK?0:1;}11. 编译程序Linux 下通常需要链接 libcurlgcc main.c-omain$(pkg-config--cflags--libslibcurl)也可以直接使用gcc main.c-omain-lcurl运行./main程序会请求https://example.com并将响应内容保存到response.html12. 将响应保存到内存如果不想写入文件而是想把响应内容保存到内存可以定义一个结构体#includestdlib.h#includestring.hstructMemory{char*data;size_tsize;};回调函数staticsize_tmemory_callback(char*ptr,size_tsize,size_tnmemb,void*userdata){size_ttotalsize*nmemb;structMemory*memory(structMemory*)userdata;char*new_datarealloc(memory-data,memory-sizetotal1);if(new_dataNULL){return0;}memory-datanew_data;memcpy(memory-datamemory-size,ptr,total);memory-sizetotal;memory-data[memory-size]\0;returntotal;}使用方式structMemorymemory{.dataNULL,.size0};curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_callback);curl_easy_setopt(curl,CURLOPT_WRITEDATA,memory);CURLcode rescurl_easy_perform(curl);if(resCURLE_OK){printf(received %zu bytes\n,memory.size);printf(%s\n,memory.data);}free(memory.data);如果响应内容是二进制数据不应该使用%s输出而应该根据memory.size处理fwrite(memory.data,1,memory.size,stdout);13. 资源清理顺序基本清理顺序如下fclose(fp);curl_easy_cleanup(curl);curl_global_cleanup();如果不再使用 curl可以写curl_easy_cleanup(curl);curlNULL;但需要注意curl_easy_cleanup()之后不能再使用该 handlecurl_global_cleanup()应该在所有 easy handle 都清理之后调用free()、fclose()等用户自己创建的资源也要自行释放。14. 初学者容易犯的错误错误一没有检查 curl_easy_initCURL*curlcurl_easy_init();curl_easy_setopt(curl,...);如果初始化失败curl 可能为 NULL应该先判断。错误二把回调数据当作字符串错误示例printf(%s,ptr);ptr 不一定以\0结束正确做法是fwrite(ptr,1,size*nmemb,stdout);错误三忽略回调函数返回值如果回调函数返回的数据长度少于size * nmemblibcurl 通常会认为写入失败returntotal;错误四只判断 CURLcode不判断 HTTP 状态码curl_easy_perform(curl);返回CURLE_OK只说明请求过程完成仍然应该通过curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,response_code);检查 HTTP 状态码。错误五忘记设置超时默认情况下某些网络问题可能导致程序等待很长时间建议至少设置curl_easy_setopt(curl,CURLOPT_CONNECTTIMEOUT,10L);curl_easy_setopt(curl,CURLOPT_TIMEOUT,30L);总结一个最基本的 libcurl 请求流程是curl_global_init(...);// 全局初始化curlcurl_easy_init();// 创建 CURL 对象curl_easy_setopt(...);// 设置 URL、回调等参数curl_easy_perform(curl);// 执行请求curl_easy_cleanup(curl);// 清理 CURL 对象curl_global_cleanup();// 全局清理响应数据处理的核心是curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,callback);curl_easy_setopt(curl,CURLOPT_WRITEDATA,userdata);其中CURLOPT_WRITEFUNCTION指定数据处理函数CURLOPT_WRITEDATA指定传给回调函数的用户参数回调函数必须按照size * nmemb处理数据返回值必须是实际处理的字节数。

相关新闻

基于二阶锥规划的主动配电网最优潮流求解(Matlab代码实现)

基于二阶锥规划的主动配电网最优潮流求解(Matlab代码实现)

👨‍🎓个人主页 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭:行百里者,半于九十。 📋&#x1f4…

2026/7/22 16:35:43 阅读更多 →
深入解析TI HDVPSS intc_intr1中断控制器:原理、配置与实战优化

深入解析TI HDVPSS intc_intr1中断控制器:原理、配置与实战优化

1. 项目概述在嵌入式视频处理系统的开发中,中断控制器就像是整个系统的“神经中枢”,它负责接收来自各个外设的“紧急呼叫”,并决定是否、以及何时通知CPU这个“大脑”去处理。今天,我们就来深入拆解德州仪器高清视频处理子系统中…

2026/7/22 16:35:43 阅读更多 →
中国电子多项AI创新成果入选国资央企人工智能典型案例

中国电子多项AI创新成果入选国资央企人工智能典型案例

2026世界人工智能大会(WAIC)期间,国务院国资委在“智赋新质 全域焕新”企业人工智能高质量发展论坛上正式启动“国资央企智能软件工厂联合筑基工程”,包括中国电子在内的首批13家中央企业研发力量参与共建。第二批央企人工智能战略…

2026/7/22 16:35:43 阅读更多 →

最新新闻

RPCS3模拟器深度优化指南:让你的PS3游戏在PC上流畅运行

RPCS3模拟器深度优化指南:让你的PS3游戏在PC上流畅运行

RPCS3模拟器深度优化指南:让你的PS3游戏在PC上流畅运行 【免费下载链接】rpcs3 PlayStation 3 emulator and debugger 项目地址: https://gitcode.com/GitHub_Trending/rp/rpcs3 你是否曾经梦想在PC上重温《最后生还者》、《神秘海域》或《战神3》等PS3经典大…

2026/7/22 17:25:07 阅读更多 →
SPI并行模式原理与实战:突破嵌入式通信带宽瓶颈

SPI并行模式原理与实战:突破嵌入式通信带宽瓶颈

1. SPI并行模式:从串行瓶颈到高速通道的演进搞嵌入式通信的工程师,对SPI(Serial Peripheral Interface)肯定不陌生。作为板上芯片间通信的“老将”,它的四线制(SCLK, MOSI, MISO&…

2026/7/22 17:25:07 阅读更多 →
PyPtt单元测试教程:确保你的PTT脚本稳定可靠

PyPtt单元测试教程:确保你的PTT脚本稳定可靠

PyPtt单元测试教程:确保你的PTT脚本稳定可靠 【免费下载链接】PyPtt The best PTT library 项目地址: https://gitcode.com/gh_mirrors/py/PyPtt PyPtt是一款强大的PTT(批踢踢)库,为开发者提供了与PTT论坛交互的丰富功能。…

2026/7/22 17:25:07 阅读更多 →
深入解析OHCI寄存器:嵌入式USB主机底层驱动开发与调试实战

深入解析OHCI寄存器:嵌入式USB主机底层驱动开发与调试实战

1. 项目概述与核心价值如果你正在开发一个嵌入式USB主机应用,比如一个工业数据采集器、一个医疗设备的数据接口,或者一个智能家居的控制中枢,那么你迟早会碰到一个绕不开的坎:如何与USB主机控制器(USB Host Controller…

2026/7/22 17:25:07 阅读更多 →
一线观察:医美GEO行业的真实质量表现

一线观察:医美GEO行业的真实质量表现

一、痛点深度剖析 我们团队在实践中发现,医美GEO行业正陷入三重核心困境:一是获客工具同质化严重,80%的通用型大数据平台功能冗余,缺乏“医美项目-地域-人群”专属标签,某区域轻医美门诊反馈“投流转化率长期低于5%”&…

2026/7/22 17:25:07 阅读更多 →
深度解析TFA两阶段微调算法:突破少样本目标检测的终极方案

深度解析TFA两阶段微调算法:突破少样本目标检测的终极方案

深度解析TFA两阶段微调算法:突破少样本目标检测的终极方案 【免费下载链接】few-shot-object-detection Implementations of few-shot object detection benchmarks 项目地址: https://gitcode.com/gh_mirrors/fe/few-shot-object-detection few-shot-object…

2026/7/22 17:24:07 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统,尤其是像TI C6000系列这样的高性能DSP开发中,我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动,但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案? 在数字化协作环境中,消息通知系统的重要性不言而喻明。但现实情况是,企业级通知方案往往需要复杂的API对接(如企业微信、钉钉、飞书),个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点",乙方听到的是"少做几页"。甲方说"不要太复杂",乙方理解成"别放图表了"。结果交过去,甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里,是…

2026/7/22 0:00:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻