网络编程知识预备(5) ——libcurl库安装及其编程访问百度首页

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

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

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

目录

  • Libcurl库简介
  • Libcurl等三方库的通用编译方法
    • 三方库使用前通读方法
    • 库的配置、编译、安装
  • 调用libcurl编程访问百度主页
    • 代码
    • 编译注意(编译时链接库、头文件路径,运行需添加动态库为环境变量)
  • libcurl函数库常用字段解读
    • 1.curl_global_init():初始化libcurl
    • 2.curl_easy_init():拿到句柄
    • 3.curl_easy_setopt(CURL *handle, CURLoption option, parameter):设置传输选项</h3>
    • 4.curl_easy_perform():执行任务</h3>
    • 5.curl_easy_cleanup():释放内存</h3>
  • 往期文章

Libcurl库简介

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

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

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

库下载地址:库下载

在这里插入图片描述

然后发送到linux开发环境中。

Libcurl等三方库的通用编译方法

三方库使用前通读方法

解压下载的库

tar xvf curl-7.71.1.tar.bz2

进入文件夹

cd curl-7.71.1

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

先看README:

vi README

并没有发现一些特别有用的东西。

在这里插入图片描述


没关系,去看这个

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

cd docs

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

vi curl.1

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

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

重点是看INSTALL文件

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

在这里插入图片描述


卧槽,外国人在绕圈圈,大概看看INSTALL.md

在这里插入图片描述

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

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

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

./configure --help

[注意]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是静态库)

头文件主要是宏定义、声明一些函数等,具体函数实现在动态库里面。

调用libcurl编程访问百度主页

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

代码

#include <stdio.h>
#include <curl/curl.h>typedef unsigned int bool;//数据类型别名用typedef  有分号
#define true 1            //宏定义(替换)用define         无冒号
#define false 0bool getUrl(char *filename)//GET请求
{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)//POST请求
{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 ");   // 指定urlcurl_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)提示找不到头文件#include <curl/curl.h>,说明没有指明头文件的路径

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

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

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'

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

直接运行这个./a.out是会报错的(为什么我没有报错??可能是我用的Ubuntu20,老师是18.04??不,很有可能是因为我当时网络是断开的)

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中已经有了百度官网的代码。(仅贴出部分)

在这里插入图片描述


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

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

libcurl函数库常用字段解读

1.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         //没有额外的初始化。

2.curl_easy_init():拿到句柄

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

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

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

在这里插入图片描述

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

3.curl_easy_setopt(CURL *handle, CURLoption option, parameter):设置传输选项

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

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

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

第二个参数CURLoption常用的宏:

  • (1)CURLOPT_URL: 设置访问URL,就是设置访问的网址
  • (2)CURLOPT_POSTFIELDS

post请求中:以&拼接字符串的形式把参数链接起来,下篇文章提到的翔云人工智能平台OCRkey和密码就要放在这里传输。

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

CURLOPT_WRITEFUNCTION使用举例:

回调函数:网页有数据请求回来的时候,如何去处理这些数据。(做人脸识别,肯定要获得人脸识别的结果)

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

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

①陈老师的车牌识别车牌识别

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);//请求回来的所有数据都放到文件中

4.curl_easy_perform():执行任务

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

5.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)

往期文章

网络编程知识预备(1) ——了解OSI网络模型
网络编程知识预备(2) ——浅显易懂的三次握手与四次挥手
网络编程知识预备(3) ——SOCKET、TCP、HTTP之间的区别与联系
网络编程知识预备(4) ——了解HTTP协议与HTTPS协议
网络编程知识预备(5) ——libcurl库安装及其编程访问百度首页

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

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

相关文章

智能家居 (9) ——人脸识别摄像头安装实现监控功能

目录摄像头模块安装安装mjpg-streamer库开启监控功能往期文章摄像头模块安装 注意&#xff1a;安装要下电安装&#xff0c;不能带电&#xff01;连接其他硬件模块的时候也是。 安装mjpg-streamer库 树莓派利用pi Camera模块&#xff0c;通过mjpg-streamer软件获取视频&#xf…

设备树和pinctrl粗解

上次文章中 我以DS18b20为例&#xff0c;在设备树中定义了ds18b20的资源&#xff08;device&#xff09;&#xff0c;当时是依葫芦画瓢&#xff0c;没有深入探究&#xff0c;本文主要探讨下pin在设备树中的描述 参考文章&#xff1a;Linux内核中的GPIO系统之&#xff08;3&…

八大排序算法(C语言实现)

摘自&#xff1a;八大排序算法&#xff08;C语言实现&#xff09; 作者&#xff1a;2021dragon 发布时间&#xff1a; 2021-05-16 10:46:37 网址&#xff1a;https://blog.csdn.net/chenlong_cxy/article/details/116563972 目录 直接插入排序希尔排序选择排序堆排序冒泡排序快…

codeforces 1060 A

https://codeforces.com/contest/1060/problem/A 题意&#xff1a;电话号码是以8开头的11位数&#xff0c;给你n 个数问最多可以有多少个电话号码 题解&#xff1a;min&#xff08;8的个数&#xff0c;n/11&#xff09; 代码如下&#xff1a; #include <map> #include &l…

嵌入式linux 自动获取IP 及 自动校时

最近要调用百度人脸识别API做个东西&#xff0c;发现百度API在桌面端QT程序跑的贼溜&#xff0c;可以到了嵌入式板子上发现就post没了返回信息。 一、嵌入式端udhcpc自动获取IP 1.在开发板建立文件夹#mkdir /usr/share/udhcpc/ -p 2.先拷贝busybox 源码目录下的 busybox-1.27…

树莓派外设开发之控制继电器(组)

目录控制继电器控制继电器组控制继电器 选择7号引脚作为继电器信号输出控制端。 代码&#xff1a; #include <wiringPi.h> #include <stdio.h> #define SWITCHER 7 // 7为树莓派物理引脚编码和wiringPi编码。在树莓派功能名为GPIO.7int main() {int cmd;if( wiri…

[BZOJ2725/Violet 6]故乡的梦

Description Input Output Sample Input 6 7 1 2 1 2 3 1 3 4 2 4 5 1 5 6 1 1 3 3 4 6 3 1 6 4 1 2 1 3 4 3 6 5 Sample Output 7 6 Infinity 7 HINT 其实这题和[TJOI2012]桥基本差不多&#xff0c;如果不是最短路径上的边&#xff0c;那直接输出最短路即可。否则就按照[TJOI2…

智能家居 (3) ——智能家居工厂模式介绍实现继电器控制灯

目录智能家居工厂模式整体设计框架继电器控制灯代码contrlEquipments.h 文件&#xff08;设备类&#xff09;mainPro.c 文件&#xff08;主函数&#xff09;bathroomLight.c 文件&#xff08;浴室灯&#xff09;secondfloorLight.c 文件&#xff08;二楼灯&#xff09;livingro…

读《系统虚拟化-原理与实现》-第二章

x86构架及操作系统概述 x86内存构架 地址空间和地址 物理地址空间&#xff1a;内存和其他硬件资源组合到一起&#xff0c;分布在CPU的物理地址空间内&#xff0c;CPU使用物理地址索引这些资源 线性地址空间&#xff1a;一个平台只有一个物理地址空间&#xff0c;但每个程序都…

智能家居 (4) ——工厂模式火焰报警

更多干货推荐可以去牛客网看看&#xff0c;他们现在的IT题库内容很丰富&#xff0c;属于国内做的很好的了&#xff0c;而且是课程刷题面经求职讨论区分享&#xff0c;一站式求职学习网站&#xff0c;最最最重要的里面的资源全部免费&#xff01;&#xff01;&#xff01;点击进…

智能家居 (5) —— LD3320语音模块二次开发

更多干货推荐可以去牛客网看看&#xff0c;他们现在的IT题库内容很丰富&#xff0c;属于国内做的很好的了&#xff0c;而且是课程刷题面经求职讨论区分享&#xff0c;一站式求职学习网站&#xff0c;最最最重要的里面的资源全部免费&#xff01;&#xff01;&#xff01;点击进…

linux命令整理

1. mkdir ##创建目录 命令 【参数】 路径文件 参数&#xff1a; mkdir -p ##递归创建 mkdir -v ##显示创建目录的过程 示例&#xff1a; [rootXM ~]# mkdir /data [rootXM ~]# mkdir -pv test/{1..3}/{4..6} ##同时创建多个目录及子目录 mkdir: created di…

eclipse搭建SSH框架详解

2019独角兽企业重金招聘Python工程师标准>>> SSH框架是最常用的框架之一&#xff0c;在搭建SSH框架的时候总有人遇到这样&#xff0c;那样的问题。下面我介绍一下SSH框架搭建的全过程。 第一步&#xff1a;准备工作。 下载好eclipse,Struts2,Spring,Hibernate。…

龙芯派启用串口3-5

硬件平台&#xff1a;龙芯派二代 内核版本&#xff1a;linux-3.10 这几天在龙芯派上加了一个无线串口&#xff0c;决定采用串口3来连接串口&#xff0c;在龙芯派上执行 #ls /dev/ttyS* 发现只有ttyS0&#xff0c;查看设备树后发现其他串口的设备树节点都是有的&#xff0c…

智能家居 (7) ——网络服务器线程控制

目录网络线程控制代码inputCommand.hmainPro.csocketControl.c代码测试往期文章网络线程控制代码 inputCommand.h #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wiringPi.h> #include <wiringSerial.h> #include &l…

龙芯3A4000 VNC配置

安装 yum install tigervnc-server -y 拷贝配置文件 cp /lib/systemd/system/vncserver\.service /lib/systemd/system/vncserver:1.service修改配置文件 vim /lib/systemd/system/vncserver:1.service替换< USER>为用户名 配置、启动vnc systemctl enable vncs…

智能家居 (6) ——语音识别线程控制

目录语音识别线程控制代码inputCommand.hmainPro.cvoiceControl.c代码测试往期文章语音识别线程控制代码 inputCommand.h #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wiringPi.h> #include <wiringSerial.h>struc…

MIPS结构体传参

本文讲解了C语言运行在MIPS体系中结构体传参的情况 硬件平台&#xff1a;Loongson 3A3000 系统&#xff1a;uos 在《see MIPS run》中11.2.5中描述到&#xff0c;会将结构体成员压缩到各个arg寄存器中进行传递 “we have to pack the register with data to mimic the arran…

对象创建过程之二(类加载器)

2019独角兽企业重金招聘Python工程师标准>>> JAVA为我们提供了两种动态加载机制。 第一种是隐式机制。其实new一个对象和调用类的静态方法时&#xff0c;就是隐式机制在工作。 第二种是显示机制。显示的机制又有两种策略 第一种是用public static Class<?> …

Python_堆栈和队列

堆栈和队列 (1)堆栈&#xff0c;新放进去的先取出 #encodingutf-8 >>> stack [3, 4, 5] >>> stack.append(6) >>> stack.append(7) >>> print (stack) [3, 4, 5, 6, 7] >>> print (stack.pop()) 7 >>> print (stack) […