[从0到1搭嵌入式工程]libcurl常用的请求方法总结

常规信息GET请求:

CURL *curl;

curl = curl_easy_init();

url = "https://www.xxx.com/time?hmac=xx&id=xx";

curl_easy_setopt(curl, CURLOPT_CURL, url); 

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); //http 0L

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // http 0L

curl_easy_setopt(curl, CURLOPT_CAINFO, "/home/app/ca/myca.crt"); //HTTP 没有这句

curl_easy_perform(curl);

curl_easy_clearup(curl);

这样,请求就完成了。 那么后台返回了什么结果,怎么办。

1,curl_easy_perform在执行时,会输出请求和结果的完整文本,所以可以通过单写一个程序,执行curl,在调用程序中,通过popen执行这个程序,获取程序执行的输出,可以从输出中解析出结果。(不是常规用法)。

2,常规用法:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &resp_data_handle); 

curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL); //下面会说到

static char g_resp_data[4096] = {};

static int g_resp_data_offset = 0;

static int resp_data_handle(void *ptr, size_t size, size_t nmemb, void* stream) {

    int this_size = size * nmemb;

    if(g_resp_data_offset + this_size < 4096 ){

    memcpy(g_resp_data+g_resp_data_offset, ptr, this_size);

    g_resp_data_offset += this_size;}

    return this_size; }

首先,resp_data_handle 这个函数是注册给curl的回调函数,有数据返回,就会调用handle函数,所以接收到的数据不是全部的数据,需要自己在handle中拼接。这样,我们就可以在从curl_easy_clearup后g_resp_data得到返回结果。

其次,CURLOPT_WRITEDATA设置的指针,如果同时设置了write function函数,则这个指针会作为function的第四个参数,传递给write function, 在function中,自己对这个指针进行操作, 如果不需要,就设置成NUL。如果没有设置 write function, WRITEDATA设置一个FILE *的文件指针, 那么,默认的回调函数,会把返回数据写入该文件中去。


上传文件

fp = fopen(filename, "rb");

fseek(fp, 0, SEEK_END);

file_size = ftell(fp);

rewind(fp);

curl_easy_setopt(curl, CURLOPT_PUT, 1L);

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L);//s

curl_easy_setopt(curl, CURLOPT_READFUNCTION, &read_file);

curl_easy_setopt(curl, CURLOPT_READDATA, fp);

curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size);

相比GET请求,多方法设置,read函数。

static size_t read_file(void *buff, size_t size, size_t nmemb, void* userpf){

    len = fread(buff, size, nmemb, (FILE *)userpf);

    return len; }

自己从文件中把数据读到buff中。

对于上传的文件,如果自身是加密的,可以使用HTTP协议。


下载

fp = fopen(filename, "wb");

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &downloadPackage);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);

curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);//设置为false,有进度,下面设置进度处理函数

curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressFunc);

curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);//跟踪重定向

curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);//在多线程处理场景下,会忽略signals对应的处理函数

curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1L);

curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 30L);//和limit合在一起使用,在30s内,如果还没有接收到一个字节,就认为速度太慢,abort。

static int g_downloaded_size = 0;//在知道int不会被溢出的情况下。这个值可以定义在userdata的结构体里,在回调时,和pf一起传进去, 就不需要定义成一个全局的。

static int downloadPackage(void *ptr, int size, int nmemb, void *userdata){

    int written_size = fwrite(ptr, size, nmemb, (FILE *)userdata);

    g_downloaded_size += size*nmemb;

    return written_size; }

static int progressFunc(void *ptr, double total_to_download, double now_downloaded, double total_to_upload, double now_uploaded ){

    if(total_to_download > 0)   

        downloaded_progress = (int)(now_downloaded/total_to_download * 100) ; }

perform执行完成后, g_downloaded_size就是我们自己记录的下载size, 再调用

double curl_downloaded_size = 0.0;

curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curl_downloaded_size);

if(g_downloaded_size == (int)curl_downloaded_size) 认为下载成功。

这就是一个简单的文件下载过程,下载完成之后,还可以通过md5sum,和线上进行比对,判断文件和服务器一致。

猜你喜欢

转载自blog.csdn.net/bingyu880101/article/details/80263430