当前位置: 首页 > backend >正文

libcurl简单使用

libcurl库的使用

1. libcurl库的编译

  • 下载curl-7.77.0.tar.gz,进行解压

    注意版本,否则可能存在编译问题

  • 执行./configure

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意指定项:

可以从docs目录下的install.md文件中查看具体详情

在这里插入图片描述

如果报错:

在这里插入图片描述

附加选项即可,比如--with-wolfssl

在这里插入图片描述

  • 接下来执行makemake install

在这里插入图片描述

出现_install目录即正确

总结:
./configure --prefix=$HOME
make
make install

2.libcurl库使用

通过libcurl的Easy interface API,开发者可以轻松地进行网络通信

主要使用:

#初始化和清理
curl_easy_init()
curl_easy_cleanup()
#设置url和选项
curl_easy_setopt()
#执行请求
curl_easy_perform()
#错误处理
curl_easy_strerror()
const char *curl_easy_strerror(CURLcode error);
curl_global_init()

函数原型

CURLcode curl_global_init(long flags)
  • 函数返回值为CURLcode类型的错误代码

    • 返回值为CURLE_OK表示初始化成功
    • 其他返回值表示初始化过程中出现了错误。
  • 参数flags是一个标志位,用于设置全局初始化的选项

    • CURL_GLOBAL_ALL: 初始化所有的支持的功能

      包括线程安全、DNS解析、SSL等

    • CURL_GLOBAL_SSL: 只初始化SSL相关的功能

    • CURL_GLOBAL_WIN32: 只适用于Windows平台

    • CURL_GLOBAL_NOTHING: 表示libcurl在全局初始化时不初始化任何功能。

  • curl_easy_init()调用时自动调用curl_global_init()
  • curl_global_cleanup()不是线程安全的,不要在每个线程都调用,在主线程调用
curl_global_cleanup()
void curl_global_cleanup(void);

该函数用于清理和释放libcurl库的全局资源。在程序退出之前,应调用该函数来确保释放libcurl占用的系统资源。

  • curl_global_cleanup()函数应在最后一个curl_easy_cleanup()函数调用之后进行调用。

    全局清理会关闭所有的libcurl句柄和资源

  • 如果没有进行全局初始化curl_global_init(),则无需调用curl_global_cleanup()

    全局清理是可选的


#include <stdio.h>
#include <curl/curl.h>
int main(){//初始化CURLcode res=curl_global_init(CURL_GLOBAL_ALL);if(res != CURLE_OK){//打印错误信息fprintf(stderr,"curl_global_init() fails:%s\n",curl_easy_strerror(res));}else{printf("curl_global_init() successful\n");}//清理curlcurl_global_cleanup();return 0;
}
curl_easy_init()
CURL *curl_easy_init(void);
  • 该函数用于创建并返回一个CURL句柄,用于执行curl请求。
  • 该句柄可以用于执行各种curl请求操作,如发送HTTP请求、获取响应、设置请求选项等。

该函数返回一个指向CURL句柄的指针,如果初始化成功,将返回非NULL的指针;否则返回NULL指针。

curl_easy_cleanup()
void curl_easy_cleanup(CURL *handle);
  • 参数handle是一个指向CURL句柄的指针,表示需要清理和释放的句柄。
  • 如果在程序中有多个CURL句柄,每个句柄都需要调用curl_easy_cleanup()进行清理和释放。

该函数意味着会话的开始,后续所有操作都针对某个指针进行,该指针称为句柄。

curl_easy_setopt()

一个用C写的API函数,用于设置CURL会话的各种选项。

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);

通过该函数,可以设置URL、请求头、请求方法、超时时间等等。

该函数很重要,curl的所有设置都在该函数内完成

  • handle:CURL会话句柄,即通过curl_easy_init()函数初始化得到的指针。

  • option:要设置的选项,是一个预定义的枚举值,表示需要设置的具体选项。

    一些常见的CURLoption选项的参数

    1. URL相关参数
    2. 调试和信号处理参数
    3. SSL参数
    4. 请求头信息参数
    5. 分类:回调
  • parameter:选项的参数值,根据具体的选项而不同。

分类:请求头信息参数
CURLOPT_HEADER:默认为0。指定写回调函数WRITEFUNCTION是否包含报文的头部信息。
CURLOPT_HTTPHEADER:CURLOPT_HTTPHEADER是一个curl_slist结构体类型的参数,它允许用户自定义HTTP请求的头信息。HTTP头部用于在请求中传递额外的信息,如身份验证凭据、自定义标头字段等
设置:CURLOPT_HTTPHEADER
  • CURLOPT_HTTPHEADER参数允许用户自定义HTTP请求的头信息
  • 通过设置curl_slist结构体来添加和管理自定义的头信息。

在这里插入图片描述

//curl_slist_append用于向curl_slist结构中添加新的字符串元素
struct curl_slist *curl_slist_append(struct curl_slist *list,const char *string);
/*
返回值是一个指向更新后字符串列表的指针:如果添加成功,返回的指针将指向新的字符串列表;如果添加失败,返回的指针将与list参数相同。
*/
//curl_slist是libcurl库中用于存储字符串列表的数据结构。它被定义为一个结构体
struct curl_slist {char *data;           // 字符串数据struct curl_slist *next;  // 指向下一个元素的指针
};
//该函数用于释放整个字符串链表及其节点所占用的内存
void curl_slist_free_all(struct curl_slist *list);

使用完curl_slist结构后,应该使用curl_slist_free_all函数释放链表内存,以避免内存泄漏。


 struct curl_slist *headers = NULL;headers=curl_slist_append(headers,"ACCEPT: application/json");headers=curl_slist_append(headers,"Content-Type: application/json");struct curl_slist *cur=headers;while(cur){printf("%s\n",cur->data);cur=cur->next;}//释放内存curl_slist_free_all(headers);

curl_easy_setopt()函数可以设置多个选项,以满足具体的请求需求。

curl_easy_perform

用于执行通过curl_easy_setopt()函数设置的CURL请求。

CURLcode curl_easy_perform(CURL *handle);

函数返回值:函数返回一个CURLcode枚举类型的结果,用于指示请求执行的状态。

如果返回CURLE_OK,表示请求执行成功;如果返回非零错误码,则表示发生了错误。

  • CURLE_OK: 请求成功完成。
  • CURLE_UNSUPPORTED_PROTOCOL: 不支持的协议,由URL的头部指定。
  • CURLE_COULDNT_CONNECT: 无法连接到远程主机或代理。
  • CURLE_REMOTE_ACCESS_DENIED: 访问被拒绝。
  • CURLE_HTTP_RETURNED_ERROR: HTTP返回错误。
  • CURLE_READ_ERROR: 读取本地文件错误。

在调用curl_easy_perform()之前,必须通过curl_easy_setopt()函数设置所需的选项:如URL、请求头、请求方法、请求体等。

#include <stdio.h>
#include <curl/curl.h>
int main(){//初始化CURL *curl=curl_easy_init();if(curl==NULL){fprintf(stderr,"curl_easy_init() failed\n");return 1;}//设置URLcurl_easy_setopt(curl,CURLOPT_URL,"http://www.baidu.com");//执行CURLcode res=curl_easy_perform(curl);if(res != CURLE_OK){fprintf(stderr,"curl_easy_perform() failed:%s\n",curl_easy_strerror(res));curl_easy_cleanup(curl);return 1;}//清理curl_easy_cleanup(curl);return 0;
}

总结:

  • 调用curl_global_init()初始化libcurl,调用curl_global_cleanup()清理全局curl句柄
  • 调用curl_easy_init()函数得到 easy interface型指针
  • 调用curl_easy_setopt()设置传输选项
  • 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务
  • 调用curl_easy_perform()函数完成传输任务
  • 调用curl_easy_cleanup()释放内存

几个应用

get请求

#include <stdio.h>
#include <curl/curl.h>
//c语言不支持bool类型
typedef unsigned int bool;
#define true 1
#define false 0
bool getURL(char* filename){//创建句柄CURL* curl;//文件句柄FILE* fp;//返回状态码CURLcode res;//打开文件失败if((fp=fopen(filename,"w"))==NULL){perror("open file fails!!\n");return false;}//设置HTTP头struct curl_slist* headers=NULL;//Accept是标准的HTTP的头字段curl_slist_append(headers,"Accept:Agent-007");//初始化curl=curl_easy_init();if(curl){//非NULL//设置optcurl_easy_setopt(curl,CURLOPT_HEADER,headers);//改协议头curl_easy_setopt(curl,CURLOPT_URL,"http://www.baidu.com");//指定HTTP请求的目标url/* 设置HTTP响应的头部和正文都写入到同一个文件 *///CURLOPT_WRITEDATA用来接收服务器响应的数据curl_easy_setopt(curl,CURLOPT_WRITEDATA,fp);//作用是将 HTTP 响应头部数据写入指定的位置,而不是响应的主体数据(body)curl_easy_setopt(curl,CURLOPT_HEADERDATA,fp);/*开始执行*/res=curl_easy_perform(curl);if(res!=CURLE_OK){fprintf(stderr,"curl_easy_perform() fails:%s",curl_easy_strerror(res));curl_slist_free_all(headers);curl_easy_cleanup(curl);return false;}}else{//打印错误fprintf(stderr,"curl_easy_init() fails!\n");fclose(fp);return false;}fclose(fp);return true;
}
int main(){getURL("hello.html");return 0;
}
#include <stdio.h>
#include <curl/curl.h>
int main(){CURL *curl;FILE *fp;CURLcode res;//全局初始化curl_global_init(CURL_GLOBAL_DEFAULT);//初始化句柄curl=curl_easy_init();//初始化文件fp=fopen("mm.txt","wb");if(fp==NULL){perror("open files fails\n");return 1;}//成功if(curl){struct curl_slist* headers=NULL;curl_slist_append(headers,"Accept:text/html");curl_easy_setopt(curl,CURLOPT_HEADER,headers);curl_easy_setopt(curl,CURLOPT_URL,"http://cn.bing.com/");//保存正文数据curl_easy_setopt(curl,CURLOPT_WRITEDATA,fp);//保存响应头部数据curl_easy_setopt(curl,CURLOPT_HEADERDATA,fp);/*执行*/res=curl_easy_perform(curl);if(res!=CURLE_OK){//出错fprintf(stderr,"curl_easy_perform() fails:%s\n",curl_easy_strerror(res));}/*清理*/curl_slist_free_all(headers);curl_easy_cleanup(curl);fclose(fp);}else{perror("curl_easy_init() fails\n");;}//全局关闭句柄curl_global_cleanup();return 0;
}

回调函数

CURLOPT_WRITEFUNCTIONCURLOPT_WRITEDATE

在使用 libcurl 进行网络请求时,CURLOPT_WRITEFUNCTIONCURLOPT_WRITEDATA 是用来接收和处理服务器返回数据的两个非常重要的设置项,而它们的核心概念是 回调函数(Callback Function)

也就是说:回调函数是当网页有数据返回时进行数据处理的函数

回调函数你把一个函数地址(指针)传给另一个函数,在特定事件发生时,这个函数会被“回调”执行。

  • 通俗理解:你告诉libcurl,“当你收到数据时,请调用我这个函数来处理这些数据。”
  • 回调函数一般由你自己定义,用于处理异步或框架层的数据。
选项用途
CURLOPT_WRITEFUNCTION设置接收数据的回调函数
CURLOPT_WRITEDATA设置传给回调函数的用户指针(一般用于传递保存数据的变量)
CURLOPT_WRITEFUNCTION

这个选项设置 libcurl在收到数据时应该调用哪个函数

size_t write_callback(char* ptr, size_t size, size_t nmemb, void* userdata);
//ptr: 指向返回的数据缓冲区的指针
//size: 每个元素的大小(通常是1)
//nmemb: 元素个数(所以实际大小是 size * nmemb)
//userdata: 你通过 CURLOPT_WRITEDATA 传入的自定义数据指针
/*返回值:必须返回实际处理的字节数(size * nmemb),否则libcurl会认为写入失败*/
CURLOPT_WRITEDATA

这个选项设置的是传给 write_callback 的最后一个参数 userdata

  • 通常你会把一个 std::string* 或文件指针传进去,用于在回调中存储数据。
  • 例如:你想把返回数据写入 std::string buffer;,就把 &buffer 作为 WRITEDATA
CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
回调函数原型为 :
size_t function( void *ptr, size_t size,size_t nmemb, void *stream); 
libcurl一旦接收到http头部数据后将调用该函数。
CURLOPT_WRITEDATA 传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION函数的stream指针的来源。
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
typedef unsigned int bool;
#define true 1
#define false 0
/*回调函数固定格式*/
size_t datafun(char* ptr, size_t size, size_t nmemb, void* userdata) {char buffer[1024]={'\0'};strncpy(buffer,ptr,1024);printf("====================get DATA=======================\n");printf("%s\n",buffer);
}
bool getURL(const char* filename){FILE *fp;CURL *curl;CURLcode res;if((fp=fopen(filename,"w"))== NULL){return false;}/*初始化*/curl=curl_easy_init();if(curl){/*设置属性*/struct curl_slist* headers=NULL;headers=curl_slist_append(headers,"Accept:Agent-007");//HTTPHEADER---别忘了HTTPcurl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);//CURLOPT_URLcurl_easy_setopt(curl,CURLOPT_URL,"http://www.baidu.com");//两个DATAcurl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,datafun);/*执行*/res=curl_easy_perform(curl);if(res != CURLE_OK){fprintf(stderr,"curl_easy_perform() fails:%s",curl_easy_strerror(res));curl_slist_free_all(headers);curl_easy_cleanup(curl);return false;}fclose(fp);curl_slist_free_all(headers);curl_easy_cleanup(curl);return true;}
}
int main(){getURL("mm.html");return 0;
}
size_t headfun(char* ptr, size_t size, size_t nmemb, void* userdata) {char buffer[1024]={'\0'};strncpy(buffer,ptr,1024);printf("====================get head=======================\n");printf("%s\n",buffer);
}curl_easy_setopt(curl,CURLOPT_HEADERFUNCTION,headfun);

get head===
HTTP/1.1 200 OK

http://www.xdnf.cn/news/5542.html

相关文章:

  • SpringBoot 整合 Langchain4j 构建AI智能体应用
  • 《异常链机制详解:如何优雅地传递Java中的错误信息?》
  • 【RP2350】香瓜树莓派RP2350之USB虚拟串口
  • windows下安装python软件
  • Linux计划任务与进程
  • 【RP2350】香瓜树莓派RP2350之LED
  • 数字孪生概念
  • 本机的驱动
  • RoPE(旋转位置编码,参考:DeepSeek-V2)
  • Linux进程9-无名管道:1.概述、创建、读写数据、2.进程间通信、3.读写规律、4.fcntl设置阻塞、5.文件描述符概述及复制函数dup,dup2
  • Robot之VideoMimic:《Visual Imitation Enables Contextual Humanoid Control》翻译与解读
  • 安卓系统APP:志愿填报(基于Android平台的志愿填报程序)
  • LVGL环形加载器
  • Linux开机后启动Oracle数据库
  • redis数据结构-06(LRANGE、LINDEX、LSET、LREM)
  • 数字化工厂中央控制室驾驶舱系统架构文档
  • Transformer LLM
  • Linux数据库篇、第零章_MySQL30周年庆典活动
  • 关于chatshare.xyz激活码使用说明和渠道指南!
  • 3D虚拟工厂vue3+three.js
  • Babel 深度解析:现代 JavaScript 开发的桥梁
  • @RequestParam @RequestHeader @RequestBody 三者详解
  • 【英语笔记(四)】诠释所有16种英语时态,介绍每种时态下的动词变形!!含有所有时态的的动词变形汇总表格
  • C语言学习记录——深入理解指针(4)
  • 单片机-STM32部分:13、PWM
  • MongoDB
  • wget、curl 命令使用场景与命令实践
  • 数据并行基础概念知识
  • openai接口参数max_tokens改名max-completion-tokens?
  • 17前端项目----支付弹框