网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页

参考:网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页_行稳方能走远的博客-CSDN博客

 Http协议之libcurl实现 - 谢呈勖 - 博客园 (cnblogs.com)


目录

一、Libcurl库简介

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

        库的配置、编译、安装

        (1)安装位置的更改:

        (2)编译、安装

        预览

三、调用libcurl编程访问百度主页

        demo1.c

        编译(编译时链接库、头文件路径)

        运行(运行需添加动态库为环境变量)

四、libcurl函数库常用字段解读

1、curl_global_init():初始化libcurl

        参数:flags

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

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

        * 第二个参数CURLoption常用的宏

4.curl_easy_perform():执行任务

5.curl_easy_cleanup():释放内存


一、Libcurl库简介

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

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

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

库下载地址: Release 7.71.1 · curl/curl · GitHub

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第1张图片

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

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

解压下载的库

tar xvf curl-7.71.1.tar.bz2

进入文件夹

cd curl-7.71.1

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

先看 README,docs 文件夹里的 curl.1 和INSTALL文件

回到/curl-7.71.1目录下,configure --help看看

./configure --help

库的配置、编译、安装

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第2张图片

(1)安装位置的更改:

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

./configure --prefix=$PWD/_install

针对于交叉编译的配置:编译后在树莓派上用在这里插入图片描述

./configure --prefix=$PWD/_install --host=arm-linux

(2)编译、安装

make
make install

预览

这些都是要用到的头文件

在这里插入图片描述

编译是要链接库一样

gcc a.c -lwiringPi -lpthread

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

三、调用libcurl编程访问百度主页

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

demo1.c

#include 
#include 

typedef unsigned int bool;//数据类型别名用typedef  有分号
#define true 1            //宏定义(替换)用define         无冒号
#define false 0

bool 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 ");   // 指定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");
}

typedef unsigned int bool;//数据类型别名用typedef  有分号
#define true 1            //宏定义(替换)用define         无冒号
#define false 0

        类似于bool,true,faluse,这是C99标准才会支持,C++里有专门的bool类型,用来表示真或假。但是在C语言里没有这样的类型,为了修改方便直接这样替换

编译(编译时链接库、头文件路径)

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第3张图片

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

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

运行(运行需添加动态库为环境变量)

        生成了可执行文件./a.out直接运行可能会报错(我没有报错,可能是我用的Ubuntu20.04)。

        原因是运行时要链接动态库,没有添加环境变量

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

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

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第4张图片

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

四、libcurl函数库常用字段解读

Http协议之libcurl实现 - 谢呈勖 - 博客园 (cnblogs.com)

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():得到easy interface型指针,拿到句柄

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

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

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

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第5张图片

 其实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);

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

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第6张图片

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);

网络编程知识预备(6) ——libcurl库简介及其编程访问百度首页_第7张图片

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的函数。

智能家居项目目录

智能家居(1) —— 工厂模式引入&工厂模式实现继电器控制

智能家居(2) —— 工厂模式实现烟雾报警

智能家居(3) —— 串口通信(语音识别)线程控制

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

智能家居(5) —— 智能家居项目整合(语音控制线程,网络控制线程、烟雾报警线程)

网络编程知识预备(1) —— 7层OSI网络模型

网络编程知识预备(2) —— 三次握手与四次挥手、半连接状态、2MSL

网络编程知识预备(3) —— TCP流量控制(滑动窗口)、拥塞控制

网络编程知识预备(4) —— SOCKET、TCP、HTTP之间的区别与联系

网络编程知识预备(5) —— 了解应用层的HTTP协议与HTTPS协议

网络编程知识预备(6) —— libcurl库简介及其编程访问百度首页

智能家居(6) —— 香橙派摄像头安装实现监控功能

智能家居(7) —— 人脸识别 & 翔云平台编程使用(编译openSSL支持libcurl的https访问、安装SSL依赖库openSSL)

智能家居(8) —— 香橙派摄像头加入设备工厂

你可能感兴趣的:(【Linux智能家居】,服务器,http,linux)