libcurl简介及其编程应用

news2024/5/18 12:36:20

本文为学习笔记,整合课程内容以及下列文章:

其中,libcurl函数库常用字段解读部分:

参考博文:原文地址
作者:冬冬他哥哥

目录

libcurl简介

libcurl的使用

学会开源包使用的一般步骤

包的解读

重点是看INSTALL文件

库的 配置 > 编译 > 安装

编程实例:访问百度主页

代码

编译注意:

libcurl函数库常用字段解读

一、调用curl_global_init():初始化libcurl

二、调用curl_easy_init():得到 easy interface型指针,拿到句柄

三、调用curl_easy_setopt(CURL *handle, CURLoption option, parameter):设置传输选项

四、调用curl_easy_perform():完成传输任务

五、调用curl_easy_cleanup():释放内存


libcurl简介

在linux下用c语言做HTTP的编程有一种方法是依赖于这个libcurlv库,以后做跨平台网络协议相关的开发,第一个要想到的就是它。

libcurl是一个跨平台的网络协议库,支持http, https, ftp等协议,libcurl同样支持:

(1)HTTPS证书授权
(2)HTTP POST, HTTP PUT, FTP 上传
(3) HTTP基本表单上传,代理,cookies,和用户认证

库下载地址:库下载

在这里插入图片描述
然后发送到linux开发环境中。

libcurl的使用

学会开源包使用的一般步骤

我们是希望通过学会使用libcurl库来掌握一系列类似的库的使用方法,所谓触类旁通。

windows下载完库后拖拽到ubuntu,创建一个空文件,把库拉进来。

 

包的解读

解压下载的库

tar xvf curl-7.71.1.tar.bz2

进入文件夹

cd curl-7.71.1

对于这种开源的包,一定要学会它的使用:

先看README:

vi README

难受,看不懂
在这里插入图片描述
没关系,去看这个

docs文件夹很重要,一般是对README的补充

cd docs

不需要看太多,看类似于这个:提到的相关的API手册

vi curl.1

也很难受,真提取不到什么信息。

嵌入式开发变得简单了是因为嵌入式经过十几二十年的发展有很多人对其进行解读,写了很多文章。

重点是看INSTALL文件

还是重点来看看docs下的INSTALL文件,库一定要学会安装才能使用。

vi INSTALL

在这里插入图片描述 

来读一读,大概看看INSTALL.md

vi INSTALL.md

在这里插入图片描述

可以看到./configure后面没有跟任何参数就是默认安装位置了,这里我们肯定要做配置,不配置都不知道文件安装到哪里去了

make就是编译的意思
make install就是把编译的结果拷贝到根的文件夹底下

关于帮助:
在这里插入图片描述不在原本默认的路径下安装说明:
在这里插入图片描述
配置是否支持https:
在这里插入图片描述回到/http/curl-7.71.1目录下,configure --help看看 

./configure --help

可以看到上文所提及的安装路径配置:

在这里插入图片描述
也可以看到特别重要的交叉编译说明:
在这里插入图片描述

库的 配置 > 编译 > 安装

(1)安装位置的更改:

配置为:$获取当前路径,编译的时候会自动生成_install文件夹,并且把编译生成的东西全部放入这个文件夹。

./configure --prefix=$PWD/_install

另外,这是针对于交叉编译的配置:编译后在树莓派上用
./configure --prefix=$PWD/_install --host=arm-linux
这样,在ubuntu中就会使用arm-gcc进行编译 

(2)开始编译

make

(3)安装

make install

4)预览

进入 /_install

我们用的是头文件

cd include

进入里面的这个

cd curl

这些都是要用到的头文件
在这里插入图片描述就像树莓派编译是要链接库一样

gcc a.c -lwiringPi -lpthread

用到这个库的时候,我们同样需要链接_install/lib里面的libcurl.so动态库 (.a是静态库) 

编程实例:访问百度主页

_install里的内容结合一下示例代码来访问一下百度。

代码

#include <stdio.h>
#include <curl/curl.h>

typedef unsigned int bool;//数据类型别名用typedef
#define true 1            //宏定义用define
#define false 0

bool getUrl(char *filename)
{
        CURL *curl;
        CURLcode res;
        FILE *fp;
        if ((fp = fopen(filename, "w")) == NULL)  // 返回结果用文件存储
                return false;
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Accept: Agent-007");
        curl = curl_easy_init();    // 初始化
        if (curl)
        {
                //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头
                curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com");
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //将返回的http头输出到fp>指向的文件,即为filename文件,而传入的参数是 /tmp/get.html,即为真正保存在get.html文件中
                curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //将返回的html主体数据输出到fp指向的文件
                res = curl_easy_perform(curl);   // 执行
                if (res != 0) {

                        curl_slist_free_all(headers);  //释放句柄
                        curl_easy_cleanup(curl);
                }
                fclose(fp);
                return true;
        }
}
bool postUrl(char *filename)
{
        CURL *curl;
        CURLcode res;
        FILE *fp;
        if ((fp = fopen(filename, "w")) == NULL)
                return false;
        curl = curl_easy_init();
        if (curl)
        {
                curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie文件
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");    // 指定post内容:用户信息,尝试登陆新浪邮箱
                //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");
                curl_easy_setopt(curl, CURLOPT_URL, " http://mail.sina.com.cn/cgi-bin/login.cgi ");   // 指定url
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
                res = curl_easy_perform(curl);
                curl_easy_cleanup(curl);
        }
        fclose(fp);
        return true;
}
int main(void)
{
        getUrl("/tmp/get.html");
        postUrl("/tmp/post.html");
}

为什么要有最开始的那三句代码呢?
类似于bool,true,faluse,这是C99标准才会支持,C++里有专门的bool类型,用来表示真或假。但是在C语言里没有这样的类型,为了修改方便直接这样替换。 

编译注意:

链接库和头文件再编译,同时注意指明他们的路径

gcc getAndPost.c -I ./curl-7.71.1/_install/include/ -L ./curl-7.71.1/_install/lib/ -lcurl

注意了,动态库静态库的链接用-L,而头文件用-I

错误排查:

(1)如果只是使用-L是默认去usr/lib下去找的,会提示找不到cannot find -lcurl

(2)如果编译报错一堆函数不认识,函数是存在库里面的,说明没有链接库

usr/bin/ld: getAndPost.c:(.text+0x1a2): undefined reference to `curl_easy_init'
/usr/bin/ld: getAndPost.c:(.text+0x1d2): undefined reference to `curl_easy_setopt'
/usr/bin/ld: getAndPost.c:(.text+0x1f6): undefined reference to `curl_easy_setopt'
/usr/bin/ld: getAndPost.c:(.text+0x217): undefined reference to `curl_easy_setopt'
/usr/bin/ld: getAndPost.c:(.text+0x238): undefined reference to `curl_easy_setopt'
/usr/bin/ld: getAndPost.c:(.text+0x244): undefined reference to `curl_easy_perform'

(3)提示找不到头文件#include <curl/curl.h>,说明没有指明头文件的路径 

可以看到已经生成了可执行文件./a.out

直接运行这个./a.out是会报错的

error while loading shared libraries: libcurl.so.4:cannot open shared object file:no such file or directory

原因是没有添加环境变量,忘记怎么添加咋办?面向百度,export lib path

export LD_LIBRARY_PATH=./curl-7.71.1/_install/lib/

成功运行后,可以看到vi /tmp/get.html中已经有了百度官网的代码。(仅贴出部分)

vi /tmp/get.html

在这里插入图片描述

这跟我们平常去访问百度是一样的,只是用了前端css去排版的比较好看罢了,当你右键查看页面源码就知道了。

vi /tmp/port.html里面不会有东西,因为访问失败了:新浪的用户和密码不匹配。

libcurl函数库常用字段解读

一、调用curl_global_init():初始化libcurl

函数只能用一次。(其实在调用curl_global_cleanup 函数后仍然可再用)

如果这个函数在curl_easy_init函数调用时还没调用,它将由libcurl库自动调用,所以多线程下最好主动调用该函数以防止在线程中curl_easy_init时多次调用。

注意:虽然libcurl是线程安全的,但curl_global_init是不能保证线程安全的, 所以不要在每个线程中都调用curl_global_init,应该将该函数的调用放在主线程中。 

参数:flags

CURL_GLOBAL_ALL               //初始化所有的可能的调用。(最常用)
CURL_GLOBAL_SSL              //初始化支持 安全套接字层。
CURL_GLOBAL_WIN32            //初始化win32套接字库。
CURL_GLOBAL_NOTHING         //没有额外的初始化。

二、调用curl_easy_init():得到 easy interface型指针,拿到句柄

用来初始化一个CURL的指针(有些像返回FILE类型的指针一样)。相应的在调用结束时要用curl_easy_cleanup函数清理。

一般curl_easy_init意味着一个会话的开始. 它会返回一个easy_handle(CURL*对象), 一般都用在easy系列的函数中。

后续所有的操作都是对这个指针进行设置,把这种类型的指针就叫做句柄,实例:

在这里插入图片描述

其实socket服务器再socket函数后生成的fd,后续的bind,accept等操作也是基于这个fd,也可以理解为句柄 

三、调用curl_easy_setopt(CURL *handle, CURLoption option, parameter):设置传输选项

根据设置的传输选项,实现回调函数以完成用户特定任务(设置与操作句柄)

这个函数最重要了.几乎所有的curl 程序都要频繁的使用它.它告诉curl库.程序将有如何的行为. 比如要查看一个网页的html代码等.(这个函数有些像ioctl函数)

参数:
(1)CURL类型的指针
(2)CURLoption类型的选项.(都在curl.h库里有定义,man 也可以查看到)
(3)parameter 既可以是个函数的指针,也可以是某个对象的指针,也可以是 个long型的变量,取决于第二个参数。

CURLoption常用的选项:
(1)CURLOPT_URL:设置访问URL,就是设置访问的网址
(2)CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
回调函数:网页有数据请求回来的时候,如何去处理这些数据。(做人脸识别,肯定要获得人脸识别的结果)

设置的回调函数格式要求为:
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);

函数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能,如处理下载文件。

CURLOPT_WRITEFUNCTION使用举例
①陈老师的车牌识别车牌识别

int BufferWriterFunc(char* data,size_t size,size_t nmemb,char *buffer)
{
	strcpy(bufferData,data);//把返回的data数据放在本地的bufferData数组中
	return size*nmemb;
}

//配置如下:
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,BufferWriterFunc);

②修改上面访问百度的代码

size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
{
	char buf[1024] = {'\0'};
	strncpy(buf,ptr,1024);
	printf("===========get data ===========\n");
	printf("%s\n",buf);
}

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,readData);

CURLOPT_WRITEDATA使用举例

也可以通过 CURLOPT_WRITEDATA属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。

正如上面访问百度的例子:

FILE *fp;
if ((fp = fopen(filename, "w")) == NULL)//提前打开了一个文件流
        return false;

curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);//请求回来的所有数据都放到文件中

(3)CURLOPT_POSTFIELDS

在post请求中:以&拼接字符串的形式把参数链接起来

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86");    // 指定post内容:用户信息,尝试登陆新浪邮箱

下片文章提到的翔云人工智能平台OCRkey和密码就要放在这里传输。

四、调用curl_easy_perform():完成传输任务

在初始化CURL类型的指针 以及curl_easy_setopt完成后调用. 就像字面的意思所说perform就像是个舞台.让我们设置的option 运作起来。

五、调用curl_easy_cleanup():释放内存

结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。

该死的a库不好用

./a.out: /usr/lib/arm-linux-gnueabihf/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by ./curl-7.71.1/_install/lib/libcurl.so.4)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark 核心编程

文章目录Spark 核心编程一、RDD1、分布式计算模拟(1) 搭建基础的架子(2) 客户端向服务器发送计算任务Spark 核心编程 Spark 计算框架为了能够进行高并发和高吞吐的数据处理&#xff0c;封装了三大数据结构&#xff0c;用于处理不同的应用场景。三大数据结构分别是&#xff1a;…

【数据结构与算法理论知识点】1.1基本概念

1.1基本概念 为什么要学习数据结构与算法&#xff1f; AlgorithmsData StructuresPrograms---- Niklaus Wirth ( Pascal程序设计语言之父、结构化程序设计首创者、图灵奖获得者) 计算机程序&#xff1a;使用计算机求解问题算法是求解问题的步骤的描述&#xff1a;从蛮力到策…

套接字编程(二)UDP服务端与客户端的通信模拟实现

目录 一、前言 二、UDP客户端流程信息 1、创建套接字 2、为套接字绑定地址信息&#xff08;不推荐&#xff09; 3、发送数据&#xff08;将数据放入发送缓冲区中&#xff09; 4、接收数据&#xff08;从socket结构体接收缓冲区中取出数据&#xff09; 5、关闭套接字 三…

机器学习基本概念及问题梳理

前言&#xff1a;整理西瓜书第一、二章中的基本概念 待办&#xff1a;第二章评估方法、性能度量及后续内容未整理 下图梳理机器学习中部分概念 模型评估与选择相关知识点&#xff1a; 错误率&#xff08;error rate, E&#xff09;&#xff1a;如果在m个样本中有a个样本分类…

WordPress安全指南:19个步骤让您的WordPress安全防线坚如磐石

谈到WordPress安全性&#xff0c;您可以采取很多措施来锁定您的网站&#xff0c;以防止黑客和漏洞影响您的电子商务网站或博客。您最不想发生的事情是一天早上醒来发现您的网站一团糟。因此&#xff0c;今天我们将分享许多技巧、策略和技术&#xff0c;您可以使用这些技巧、策略…

WEBSHELL管理工具流量特征——基础篇

前言 前一阵子帮别人做取证题目&#xff0c;有很多关于WEBSHELL的流量要分析&#xff0c;想起来还有没好好分析过于是准备写篇文章总结一下帮助大家能够快速的辨别WEBSHELL流量&#xff0c;下面我们展开文章来讲。 中国菜刀 这个应该是大家最熟悉的WEBSHELL管理工具&#xf…

NeuRay学习笔记

Neural Rays for Occlusion-aware Image-based Rendering 主页&#xff1a;https://liuyuan-pal.github.io/NeuRay/ 论文&#xff1a;https://arxiv.org/abs/2107.13421 Code&#xff1a;https://github.com/liuyuan-pal/NeuRay 效果&#xff1a; desktop摘要 We present a ne…

一文读懂 UniProt 数据库(2023 最新版)

一、UniProt 数据库介绍 Uniprot &#xff08;Universal Protein &#xff09;是包含蛋白质序列&#xff0c;功能信息&#xff0c;研究论文索引的蛋白质数据库&#xff0c;整合了包括EBI&#xff08; European Bioinformatics Institute&#xff09;&#xff0c;SIB&#xff0…

【面试题】前端最新面试题-浏览器 dom、bom篇

原文见&#xff1a;语雀&#xff08;https://www.yuque.com/deepstates/interview/fsitlt&#xff09; ● BOM ● window对象 ○ frames ■ iframe ■ 跨窗口通信 ■ 同源策略/跨域 ○ navigator ● DOM ○ DOM结构 ○ DOM操作 ○ DOM事件 ■ 表单事件 ● 浏览器渲染 ○ 进程、…

Vue组件化编程的组件通信

对于组件化编程&#xff0c;组件之间的通信技术无疑是非常重要的内容&#xff0c;需要将细节牢牢把握。 组件通信&#xff0c;就是子组件放置在父组件内之后&#xff0c;父组件如何向子组件传递参数以及子组件如何与外部组件进行互动。 这部分的知识很重要&#xff0c;需要展开…

基于Ubuntu20.04搭建OpenHarmony v3.0.6的qemu仿真环境

基于Ubuntu20.04搭建OpenHarmony v3.0.6的qemu仿真环境0. 前言1. 安装Ubuntu1.1 更换华为源1.2 安装必要工具2. 下载代码2.1 解压与目录设置3. 配置环境3.1 安装库和工具3.2 设置python版本3.3 安装编译工具hb3.4 切换dash为bash4. 编译4.1 hb构建4.2 启动qemu5. 第二种环境配置…

Java之日期与时间、JDK8新增日期类、包装类、正则表达式、Arrays类、常见算法和Lambda表达式

目录日期与时间DateSimpleDateFormatCalendar概述JDK8新增日期类概述、LocalTime /LocalDate / LocalDateTimeInstantDateTimeFormatterDuration/PeriodchronoUnit包装类正则表达式Arrays类Arrays类概述&#xff0c;常用功能演示Arrays类对于Comparator比较器的支持常见算法选择…

[论文翻译] GIKT: A Graph-based Interaction Model forKnowledge Tracing

摘要随着在线教育的快速发展&#xff0c;知识追踪&#xff08;KT&#xff09;已成为追踪学生知识状态并预测他们在新问题上的表现的基本问题。在线教育系统中的问题通常很多&#xff0c;并且总是与更少的技能相关联。然而&#xff0c;以往的文献未能将问题信息与高阶问题-技能相…

计网必会:电路交换和分组交换

电路交换和分组交换的概念和区别&#xff0c;为什么分组交换更有效&#xff1f; 电路交换&#xff1a;由于电路交换在通信之前要在通信双方之间建立一条被双方独占的物理通路&#xff08;由通信双方之间的交换设备和链路逐段连接而成&#xff09; 特点是源和目标点建立起名副其…

C语言中的void*是什么?

目录1.void *是什么2.void*的解引用3.void*类型的应用场景1.void *是什么 我们之前学过许多类型的指针变量&#xff0c;如整形指针&#xff0c;字符指针&#xff0c;甚至数组指针&#xff0c;函数指针等。 int a 10; int *pa &a;//整形指针pa接受一个整形变量a的地址但…

阻塞队列-BlockingQueue

一、BlockingQueue介绍BlockingQueue 继承了 Queue 接口&#xff0c;是队列的一种。Queue 和 BlockingQueue 都是在 Java 5 中加入的。阻塞队列&#xff08;BlockingQueue&#xff09;是一个在队列基础上又支持了两个附加操作的队列&#xff0c;常用解耦。两个附加操作:支持阻塞…

Win10 每天蓝屏多次,蓝屏代码0x3B:SYSTEM_SERVICE_EXCEPTION

环境&#xff1a; 联想E14笔记本 Win10 专业版 问题描述&#xff1a; Win10 每天发生蓝屏多次&#xff0c;蓝屏代码0x3B:SYSTEM_SERVICE_EXCEPTION 查看事件查看器&#xff0c;系统日志筛选ID1001的事件,蓝屏多次基本上都是3B这错误代码 解决方案&#xff1a; 1.禁用AMD显…

vue3 pinia 状态管理(清晰明了)

前言 最近学习cloud项目&#xff0c;前端使用到 vue3 ts 等技术&#xff0c;其中包括 pinia &#xff0c;从一脸懵到渐渐清晰过程&#xff0c;在此记录一下&#xff0c;若有不足&#xff0c;希望大佬可以指出。 中文官方文档&#xff1a;https://pinia.web3doc.top/ 一、什…

2022年海南省职业院校技能大赛“网络安全”比赛任务书

2022年海南省职业院校技能大赛“网络安全” 比赛任务书 一、竞赛时间 总计&#xff1a;360分钟 二、竞赛任务书内容 &#xff08;一&#xff09;拓扑图 &#xff08;二&#xff09;A模块基础设施设置/安全加固&#xff08;350分&#xff09; 一、项目和任务描述&#xff…

服务器怎么防勒索病毒

行业背景 随着金融行业信息化建设的飞速发展&#xff0c;金融行业信息化系统经过多年的发展建设&#xff0c;目前信息化程度已经达到了较高水平。信息技术在提高管理水平、促进业务创新、提升企业竞争力方面发挥着日益重要的作用。 需求分析 随着金融信息化的深入发展&#…