02Linux下使用libcurl(C语言)来实现http请求(数据保存至内存)(这里可以让你深入了解realloc函数)

02Linux下使用libcurl(C语言)来实现http请求(数据保存至内存)(这里可以让你深入了解realloc函数)

其它关于lincurl文章
01Linux下使用libcurl(C语言)来实现http请求(数据保存至文件)(包括下载libcurl)
02Linux下使用libcurl(C语言)来实现http请求(数据保存至内存)(这里可以让你深入了解realloc函数)

这篇是从官网的例子中学习的,里面有非常多例子让我们参考。
libcurl/c/example

前言:
上一篇我们讲到网站服务器的响应保存到文件,这篇是保存到内存的。

1 c语言中realloc()函数的作用
参考:
c语言中realloc()函数解析

realloc作用:调整已有的内存。//非常重要的理解,并不是malloc一样开辟指定大小的内存。

	//realloc作用:调整已有的内存。
	//理解以下内容:
	//1)若已有内存后面有足够的空闲位置,则直接在后面扩展缺少的内存(此时ptr=mem->response);
	//2)如若不足,则开辟新的空间并将原来内存的数据拷贝到新内存的前面部分,并且原内存被释放掉。
	//注意:如果调用成功,不管当前内存段后面的空闲空间是否满足要求,都会释放掉原来的指针,重新返回一个指针,这就导致1)的两个指针都无法再使用,只能根据返回指针使用,这里为ptr
	//并且返回的指针ptr的内存已经由另一个进程管理,不需要我们在free(ptr),类似智能指针,所以这里不再需要free任何内存,只需要realloc

	//只能使用返回值ptr
    char *ptr = realloc(mem->response, mem->size + realsize + 1);//扩展realsize + 1个字节空间(平时绝大部分都是足够的),ptr指向内存大小为mem->size + realsize + 1
    if(ptr == NULL){
		return 0;  /* out of memory! */
	}

了解上面的函数后,对下面的回调函数中的内存处理你就非常简单了。

2 例子数据保存至内存)
对比上一篇,这里只是将对应的回调函数修改即可。

#include <stdio.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>	// for open
#include <unistd.h> // for close
#include <stdlib.h> // for realloc
#include <string.h> // for memcpy

const char *userpwd = "xxxxxx";//登录网站所需的账号密码
const char *requestUrl = "xxxxxx";//要登录的url

//用于存储数据的结构体
struct memory {
    char *response;
    size_t size;
};
 
//保存网站服务器响应的信息到内存
static size_t write_data2(void *data, size_t size, size_t nmemb, void *userp){

    size_t realsize = size * nmemb;//本次响应数据的实际大小
    struct memory *mem = (struct memory *)userp;//获取用户传进的变量

	//realloc作用:调整已有的内存。1)若已有内存后面有足够的空闲位置,则直接在后面扩展缺少的内存(此时ptr=mem->response);
	//2)如若不足,则开辟新的空间并将原来内存的数据拷贝到新内存的前面部分,并且原内存被释放掉。
	//注意:如果调用成功,不管当前内存段后面的空闲空间是否满足要求,都会释放掉原来的指针,重新返回一个指针,这就导致1)的两个指针都无法再使用,只能根据返回指针使用,这里为ptr
	//并且返回的指针ptr的内存已经由另一个进程管理,不需要我们在free(ptr),类似智能指针,所以这里不再需要free任何内存,只需要realloc

	//只能使用返回值ptr
    char *ptr = realloc(mem->response, mem->size + realsize + 1);//扩展realsize + 1个字节空间(平时绝大部分都是足够的),ptr指向内存大小为mem->size + realsize + 1
    if(ptr == NULL){
		return 0;  /* out of memory! */
	}
    
	//交给mem->response使用
    mem->response = ptr;

	//从下标为size的地址开始存储本次的响应数据,数据大小为realsize
	memcpy(&(mem->response[mem->size]), data, realsize);
    //memcpy_s(&(mem->response[mem->size]), realsize, data, realsize);只有windows下有
    mem->size += realsize;//将用户已有的数据大小也累积进去

    mem->response[mem->size] = 0;//这里是多次请求时将上一次的数据清掉,当对于项目只需要单次请求的可以注释掉,已经测试过。(但最好留着反正没碍着)

    return realsize;
}


//Get请求(默认)
int http_client_request(CURL **handle, const char *url, void *userp){

	if (!url) {
       return -1;
    }

    //1 初始化libcurl,设置默认参数
    CURLcode return_code;
    return_code= curl_global_init(CURL_GLOBAL_ALL);
    if (CURLE_OK != return_code) {
        printf("curl_global_init failed.\n");
        return -1;
    }

    //2 获取easy handle
    *handle = curl_easy_init();
    if (!(*handle)) {
		printf("curl_easy_init failed.\n");
        return -1;
    }

	//2 通过CURLOPT_URL属性设置url
	curl_easy_setopt(*handle,CURLOPT_URL, url);
	//注册回调函数write_cb,回调函数将会在接收到数据的时候被调用
   	//curl_easy_setopt(*handle, CURLOPT_WRITEFUNCTION, write_data);
	curl_easy_setopt(*handle, CURLOPT_WRITEFUNCTION, write_data2);
	//设置写数据的变量
	if (userp) {
       curl_easy_setopt(*handle, CURLOPT_WRITEDATA, userp);
	}
	//通过CURLOPT_USERPWD属性来设置用户名与密码。参数是”user:password “的字符串
    curl_easy_setopt(*handle,CURLOPT_USERPWD, userpwd);


	//3 使用curl_easy_perform执行上传数据
    curl_easy_perform(*handle);


    //4 任务执行结束使用curl_easy_cleanup把内存释放
	curl_easy_cleanup(*handle);

	//5 释放libcurl
	curl_global_cleanup();

	return 0;
}

int main(){

#if 0
	CURL *handle;
	int fd;
	fd = open(saveDataFileName, O_RDWR|O_CREAT);
	if(fd == -1){
		printf("open file failed.\n");
		return -1;
	}
	int ret = http_client_request(&handle, requestUrl, (void*)&fd);
	if(ret == -1){
		printf("init client falied.\n");
		close(fd);
		return -1;
	}
	close(fd);
#endif

	struct memory chunk;
	chunk.response = NULL;
	chunk.size = 0;

	CURL *handle;
	int ret = http_client_request(&handle, requestUrl, (void*)&chunk);
		if(ret == -1){
		printf("init client falied.\n");
		return -1;
	}

	if(chunk.response == NULL){
		printf("Get Response Data Failed.\n");
		return -1;
	}

	printf("=====Get Response Data Ok.=====\n");

	printf("response_size=%ld\n",chunk.size);
	printf("%s",chunk.response);

	//可以进一步拷贝至数组
	//char jsonBuf[512] = {0};
	//memcpy(jsonBuf, chunk.response, chunk.size);
	//printf("%s",jsonBuf);

	return 0;
}

执行命令和上一篇一样:

gcc curlTest.c -o curlTest -l curl
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值