掌握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处理数据返回值必须是实际处理的字节数。

相关新闻

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

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

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

2026/10/17 20:51:07 阅读更多 →
中国电子多项AI创新成果入选国资央企人工智能典型案例

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

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

2026/10/18 4:22:24 阅读更多 →
LocalAI语音识别教程:在本地设备上部署Whisper模型的完整指南

LocalAI语音识别教程:在本地设备上部署Whisper模型的完整指南

LocalAI语音识别教程:在本地设备上部署Whisper模型的完整指南 【免费下载链接】LocalAI LocalAI is the open-source AI engine. Run any model - LLMs, vision, voice, image, video - on any hardware. No GPU required. 项目地址: https://gitcode.com/GitHub_…

2026/10/18 4:22:32 阅读更多 →

最新新闻

生鲜配送商城APP实战复盘:从架构设计到履约链路与避坑指南

生鲜配送商城APP实战复盘:从架构设计到履约链路与避坑指南

1. 项目概述与核心价值先聊个现象:生鲜配送这几年看着热闹,真正做过的人才知道,这个赛道远不是"把菜送到家"这么简单。相比标品电商,生鲜的核心难点在于"鲜"和"快",这两个字考验的不是某…

2026/10/18 13:47:07 阅读更多 →
博客内容生成规范与合规边界说明

博客内容生成规范与合规边界说明

我无法根据当前输入内容生成符合要求的博文。原因如下:项目标题仅为“rea”,无明确语义,既非完整单词(如“real”“react”“realm”等常见缩写或拼写变体),也未提供上下文指向具体领域(编程、设…

2026/10/18 13:47:07 阅读更多 →
科创项目数据可视化与分析平台:从选题到部署答辩的全流程实战

科创项目数据可视化与分析平台:从选题到部署答辩的全流程实战

说实话,现在毕设题目越来越卷,既要体现工作量,又要保证做完,还得在答辩时讲出东西来。“科创项目数据可视化与分析平台”这个方向,这几年我见过不少同学在做,它属于典型的不踩雷选题:业务场景非…

2026/10/18 13:47:07 阅读更多 →
手写响应式状态管理库rea:核心设计与实战解析

手写响应式状态管理库rea:核心设计与实战解析

其实“rea”这个标题,我第一次看到的时候也愣了一下——就三个字母,没有任何上下文。但放在这几年做前端基础架构的语境里,我很快就明白过来,这多半是一个内部状态管理模块的项目代号。恰好我们团队之前也经历过一段“状态管理大乱…

2026/10/18 13:47:07 阅读更多 →
MySQL数据库和表操作详解:从建库到删表的完整指南

MySQL数据库和表操作详解:从建库到删表的完整指南

MySQL这门课我接触了十年,最早也是从“数据库和表的基本操作”入门的。说实话,刚开始觉得无非就是CREATE、DROP、ALTER那几条命令,后来在真实项目里踩了无数坑,才明白基础操作里藏着大量细节,比如字符集选错导致乱码、…

2026/10/18 13:47:07 阅读更多 →
飞凌 OK3576-C 实测:Debian 13 上的八核 CPU、eMMC、GPU 和 NPU,实际表现怎么样?

飞凌 OK3576-C 实测:Debian 13 上的八核 CPU、eMMC、GPU 和 NPU,实际表现怎么样?

拿到一块嵌入式开发板,我一般会先确认系统能否正常启动和使用,再考虑跑分。芯片参数很好查,但装上 Debian 以后,软件包是否齐全、编译是不是够快、eMMC 读写会不会拖后腿,以及 GPU 和 NPU 能否真正运行程序&#xff0c…

2026/10/18 13:46:06 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →