目录
1.CURLcode curl_global_init(long flags);
2 void curl_global_cleanup(void);
5 void curl_easy_cleanup(CURL *handle);
6 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
7 CURLcode curl_easy_perform(CURL *handle);
一、LibCurl基本编程框架
libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。想要知道更多关于libcurl的介绍,可以到官网 curl上去了解,在这里不再详述。win32版的libcurl下载地址:http://curl.freeby.pctools.cl/download/libcurl-7.18.0-win32-msvc.zip
在基于LibCurl的程序里,主要采用callback function (回调函数)的形式完成传输任务,用户在启动传输前设置好各类参数和回调函数,当满足条件时libcurl将调用用户的回调函数实现特定功能。
下面是利用libcurl完成传输任务的流程:
1. 调用curl_global_init()初始化libcurl
2. 调用curl_easy_init()函数得到 easy interface型指针
3. 调用curl_easy_setopt()设置传输选项
4. 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务
5. 调用curl_easy_perform()函数完成传输任务
6. 调用curl_easy_cleanup()释放内存
在整过过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。二、一些基本的函数
1.CURLcode curl_global_init(long flags);
描述:
这个函数只能用一次。(其实在调用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 void curl_global_cleanup(void);
描述:在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。注意:虽然libcurl是线程安全的,但curl_global_cleanup是不能保证线程安全的,所以不要在每个线程中都调用curl_global_init,应该将该函数的调用放在主线程中。
3 char *curl_version( );
描述: 打印当前libcurl库的版本。
4 CURL *curl_easy_init( );
描述:
curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样). 相应的在调用结束时要用curl_easy_cleanup函数清理.
一般curl_easy_init意味着一个会话的开始. 它会返回一个easy_handle(CURL*对象), 一般都用在easy系列的函数中.
5 void curl_easy_cleanup(CURL *handle);
描述:
这个调用用来结束一个会话.与curl_easy_init配合着用.
参数:
CURL类型的指针.
6 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
描述: 这个函数最重要了.几乎所有的curl 程序都要频繁的使用它.它告诉curl库.程序将有如何的行为. 比如要查看一个网页的html代码等.(这个函数有些像ioctl函数)参数:
1 CURL类型的指针
2 各种CURLoption类型的选项.(都在curl.h库里有定义,man 也可以查看到)
3 parameter 这个参数 既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.
CURLoption 这个参数的取值很多.具体的可以查看man手册.
7 CURLcode curl_easy_perform(CURL *handle);描述:这个函数在初始化CURL类型的指针 以及curl_easy_setopt完成后调用. 就像字面的意思所说perform就像是个舞台.让我们设置的
option 运作起来.参数:
CURL类型的指针.转载于:C++ 用libcurl库进行http通讯网络编程 - 绿色冰点 - 博客园 (cnblogs.com)
/*=============================================== * 文件名称:weather.c * 创 建 者: * 创建日期:2022年09月15日 * 描 述: ================================================*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> #include "cJSON.h" #include <sys/types.h> #include <unistd.h> //串口协议结构体相关头文件 #include <termios.h> #include <sys/stat.h> #include <fcntl.h> char uid[50]="dc656d5a1d4a4398bbfde41436a7226e"; char topic[20]="env"; char type[2] = "1"; // char msg[24]; //用 get 方法推送主题 void pushGetTopic(char *msg); //用 post 方法推送主题 void pushPostTopic(char *msg); //只能用 get 方法订阅主题 char getTopic(char *msg); //声明回调函数,用于接受网页回复的数据 size_t myRecv(void *buffer, size_t size, size_t nmemb, void *userp); void pushGetTopic(char *msg) { char url[256]={0}; sprintf(url,"https://apis.bemfa.com/va/getpushmsg?uid=%s&topic=%s&type=%s&msg=%s",uid,topic,type,msg); //全局初始化 curl库,void型,只调用一次 curl_global_init(CURL_GLOBAL_ALL); //初始化 easy interface相关接口,得到 easy_handle指针 CURL *curl = curl_easy_init(); if(curl != NULL){ //设置请求的url网址 curl_easy_setopt(curl, CURLOPT_URL,url); //不验证数字信息,1L为验证数字信息 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L);//CURLOPT_SSL_VERIFYPEER:验证SSL证书 verifypeer //设置请求的方式 curl_easy_setopt(curl,CURLOPT_CUSTOMREQUEST,"GET");//CURLOPT_CUSTOMREQUEST:自定义请求方法 customrequest //curl_easy_setopt(curl,CURLOPT_POST,0); //定义结构体指针 struct curl_slist *headers = NULL; //将头部信息追加到指针中 headers=curl_slist_append(headers,"Content-Type:application/x-www-form-urlencoded"); curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers);//CURLOPT_HTTPHEADER:自定义 HTTP 头 //设置注册回调函数 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,myRecv);//CURLOPT_WRITEFUNCTION:用于写入数据的回调 writefunction //执行请求 int errno = curl_easy_perform(curl); if(errno != CURLE_OK){ printf("执行错误:%d\n",errno); } //释放url指针 curl_easy_cleanup(curl); //释放请求头 curl_slist_free_all(headers); } //7、清除curl库的相关资源 curl_global_cleanup(); } void pushPostTopic(char *msg) { char url[256]={0}; sprintf(url,"https://apis.bemfa.com/va/postmsg?uid=%s&topic=%s&type=%s&msg=%s",uid,topic,type,msg); curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if(curl != NULL){ curl_easy_setopt(curl, CURLOPT_URL,url); //不验证数字信息 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L); //设在请求方式为 post curl_easy_setopt(curl,CURLOPT_CUSTOMREQUEST,"POST"); // curl_easy_setopt(curl,CURLOPT_POST,1); //定义结构体指针 struct curl_slist *headers = NULL; //将头部信息追加到指针中 headers=curl_slist_append(headers,"Content-Type:application/x-www-form-urlencoded"); curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers); //设置注册回调函数 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,myRecv); //执行请求 int errno = curl_easy_perform(curl); if(errno != CURLE_OK){ printf("执行错误: %d :%s\n",errno,curl_easy_strerror(errno)); } //释放url指针 curl_easy_cleanup(curl); //释放请求头 curl_slist_free_all(headers); } //7、清除curl库的相关资源 curl_global_cleanup(); } char getTopic(char *msg) { char url[256]={0}; sprintf(url,"https://apis.bemfa.com/va/getmsg?uid=%s&topic=%s&type=%s",uid,topic,type); curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if(curl != NULL){ curl_easy_setopt(curl, CURLOPT_URL,url); //不验证数字信息 curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L); // curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,"GET"); // curl_easy_setopt(curl,CURLOPT_POST,1); // //定义结构体指针 // struct curl_slist *headers = NULL; // //将头部信息追加到指针中 // headers=curl_slist_append(headers,"Content-Type:application/x-www-form-urlencoded"); // curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers); //设置注册回调函数 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,myRecv); //执行请求 int errno = curl_easy_perform(curl); if(errno != CURLE_OK){ printf("执行错误: %d :%s\n",errno,curl_easy_strerror(errno)); } //释放url指针 curl_easy_cleanup(curl); //释放请求头 // curl_slist_free_all(headers); } //7、清除curl库的相关资源 curl_global_cleanup(); } /* * 如果回复的数据是json格式∶ * 1、先使用c]S0N *c]son_Parse( char *buffer); * 函数转换成cJ5ON对象。 * 2、可以使用char * c]SON_Print(cJSON *node) ; * 函数将json对象类型数据转换成char *类型的数据。 * 3、可以使用cJSON *cSON_Get0bjectItem(cJSON *node,char *key); * 函数,取某个key的 value值。 * 4、可以使用if( node->type =- c]SON_Array)来进行判断 value值是否是一个json数组 * 5、通过使用int cJSON_GetArraysize( cJ50N *node) ; * 函数,可以获得node这个json数组中的元素个数。 * 6、可以通过cJSON *CJSON_GetArrayItem( cJSON *node,int i); * 函数,可以获得node这个json数组中下标为i的元素。 * 7、在cJSON结构体中,提供 valuestring\ valuedouble等结构体成员 * 来表示key的 value值的字符串类型、符点类型数据。 */ size_t myRecv(void *buffer, size_t size, size_t nmemb, void *userp) { printf("---%s\n",(char *)buffer); #if 0 printf("-----------------size: %ld n: %ld-----------------\n %s\n",size,nmemb,(char*)buffer); //创建cJSON对象,将buffer转换成cJSON类型 cJSON *root = cJSON_Parse((char *)buffer); //cJSON_Print():打印 cJSON 对象的内容 printf("root:%s\n",cJSON_Print(root)); //cJSON_GetObjectItem():取出某个 Key的 Value值 root = cJSON_GetObjectItem(root,"weatherinfo"); if(NULL==root){ printf("没有该数据\n"); return size*nmemb; } printf("%s\n",cJSON_Print(root)); if( root->type == cJSON_Array ){ printf("value值是一个json数组\n"); } if( root->type== cJSON_Object ){ printf("weatherinfo 的 value 值是一个JSON对象\n"); //cJSON *node = NULL; cJSON *node = cJSON_GetObjectItem(root,"temp"); if(NULL==node){ printf("没有temp数据\n"); return size*nmemb; } //node->valuestring : 获取node中的数据的字符串形式,valuestring是一个结构体成员 printf("temp:%s\n",node->valuestring); } #endif //执行完成,必须返回 size*nmemb return size*nmemb; } int main(int argc, char *argv[]) { //打开串口设备,必须确保这里的串口能够使用 int fd = open("/dev/ttyS0",O_RDWR); if(fd<0){ perror("open"); return -1; } //设置串口协议 struct termios options; tcgetattr(fd, &options); options.c_cflag |= (CLOCAL | CREAD);//忽略调制解调器线路状态 使用接收器 options.c_cflag &= ~CSIZE; //字符长度,取值范围为CS5、CS6、CS7或CS8 options.c_cflag &= ~CRTSCTS;//不使用RTS/CTS流控制 options.c_cflag |= CS8;//设置数据位 options.c_cflag &=~ CSTOPB;//不设置两个停止位,设置为1个停止位 options.c_iflag |= IGNPAR;//忽略奇偶校验错误 options.c_iflag &=~(ICRNL|IXON);//将输入的回车转化成换行(如果IGNCR未设置的情况下) 允许输入时对XON/XOFF流进行控制 options.c_oflag =0; options.c_lflag =0; cfsetispeed(&options,B115200); cfsetospeed(&options,B115200);//two is 波特率 tcsetattr(fd,TCSANOW,&options);//将串口协议设置到fd中立即生效 unsigned char buf[36] = {0}; while(1){ int count = 0; while(count<36){ int ret=read(fd,buf+count,36-count); if(ret<0) break; count += ret; } for(int i=0;i<36;i++) printf("%2d ",buf[i]); printf("\n"); char msg[8]={0}; int t = buf[4] + (int)buf[5]; sprintf(msg,"t:%d",t); printf("%s\n",msg); sleep(1); // pushGetTopic(msg); pushPostTopic(msg); printf("==================================\n"); getTopic(msg); } return 0; }
参考文档:
Linux下的libcurl库的使用(学习总结)_程序猿-小土豆的博客-CSDN博客_libcurl linux
libcurl库详解:
https://blog.csdn.net/hhltaishuai/article/details/115593271
C语言libcurl的安装以及接口的使用方法:
https://blog.csdn.net/weixin_48503637/article/details/122582089
libcurl库下载:
sudo apt-get install libcurl4-openssl-dev
liunx快速查找文件:
https://blog.csdn.net/xxmonstor/article/details/80507769
头文件目录:/usr/include/x86_64-linux-gnu/curl/curl.h串口编程:https://www.freesion.com/article/6013164167/
项目之用ARM串口关联巴法云进行推送或者订阅
于 2022-09-17 17:01:43 首次发布