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

2023-11-05

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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 肖战

    肖战是中国内地男演员 歌手 主持人 毕业于中央戏剧学院表演系 他曾出演过多部影视剧 包括 花千骨 武媚娘传奇 和 长安十二时辰 此外 他还是一位多才多艺的歌手 曾发行过多张个人音乐专辑
  • 苹果开发平台常用网址链接

    苹果开发者中心 https developer apple com cn 苹果开发者中心 企业类型 https developer apple com cn programs enterprise 注册账号 https developer
  • react+antd实现Table拖拽调整列宽

    注意 列需要传入 width 并且配合下面的css样式才能显示拖拽手势 import React useEffect useState from react import Table from antd import Resizable f
  • PE半透明屏是怎么制造的?工艺、材料、应用

    PE半透明屏是一种新型的屏幕材料 具有半透明的特点 它由聚乙烯 PE 材料制成 具有良好的透明度和柔韧性 PE半透明屏广泛应用于建筑 广告 展览等领域 具有很高的市场潜力 PE半透明屏的特点之一是其半透明性 它可以在一定程度上透过光线 使得

随机推荐

  • 相关性分析热力图(Python&Matlab代码实现)

    目录 1 热力图 1 1 简介 1 2 语法 2 算例1 Python代码实现 2 1 算例 2 2 Python代码 2 3 运行结果 3 算例2 Python代码实现 4 算例3 Python代码实现 4 1 算例 4 2 Python
  • 小电容通高频大电容通低频的理解

    本文参考为什么电容通高频阻低频 记录下个人理解并总结 1 电容的作用是通高频阻低频 高频的时候电容总是还没充满电 负半周期便到来 所以电流始终存在 低频的时候信号交流电负半周还没到来 电容已充满电便发生断路 2 理论上电容越大 能通越高的高
  • 简单解释同步、异步、阻塞、非阻塞、中断、轮询、多线程,协程这几个概念(代码未验证,仅参考)

    科普 同步和异步的区别 同步和异步是指程序执行的方式 其中同步指程序按顺序执行 每个任务必须等待前面的任务执行完成后才能执行 而异步则指程序可以在执行一个任务时同时执行另一个任务 不需要等待前一个任务执行完毕 同步 Synchronous
  • supervisor源码分析

    Supervisor分析 1 运行原理概述 Supervisor生成主进程并将主进程变成守护进程 supervisor依次生成配置文件中的工作进程 然后依次监控工作进程的工作状态 并且主进程负责与supervisorctl客户端通信 实现主
  • c语言中求三个整数中的最大值和最小值,编程用指针实现输入三个整数,求其中的最大值...

    公告 为响应国家净网行动 部分内容已经删除 感谢读者理解 话题 编程用指针实现输入三个整数 求其中的最大值回答 include stdio h int getmax int p int n int i max p max p p 0 for
  • C++ 多线程 学习笔记

    线程睡眠很稳定 但无线程睡眠不稳定 线程调用类方法 有参数时调用方法 当参数为引用时 detach分离线程 分离线程与主线程同时进行 join会使主线程挂起 执行join进来的进程 detach必须让主线程在还住运行的情况下调用 换句话说就
  • harbor数据库迁移

    harbor数据库迁移 相同版本间迁移 一 数据导出 旧harbor机 1 进入数据库容器 root localhost docker exec u root it d53efe26b3da bin bash 2 导出registry数据库
  • KafkaConsumer-Kafka从入门到精通(十)

    上篇文章说了 消息压缩可以看分情况进行 判断下服务器cpu空闲还是io空闲较多 如果cpu空闲较多 则考虑消息积压 反之则不考虑 还有消费者组 consumer group 对于同一个group 只会发送一条消息进入一个实例 位移提交在0
  • php中mail,php中mail()函数和SMTP工作原理及实际

    php中mail 函数和SMTP工作原理及实际 发表于2019 05 24 12 36 次阅读 来源网络整理 作者session 摘要 php中mail 函数和SMTP工作原理及实际 php中mail 函数和SMTP工作原理及实际 一个发送
  • C++利用zxing识别二维码

    C 利用zxing识别二维码 下载编译 配置使用 Win10 x64 VS2015 VS2019 下载编译 1 下载zxing包 并解压 下载地址 https github com glassechidna zxing cpp build文
  • linux:TCP(传输控制协议)1、客户端和服务器连接并通信客户端,向服务器发送数据2、实现回传。服务器收到客户端的数据之后,将数据返传给客户端

    注意 服务器中的ip 192 168 31 122 和端口号port 6666 客户端中必须一致 编译 客户端 gcc tcp client c o client 服务器 gcc tcp server c o server 运行 客户端 c
  • GAN的图像修复:多样化补全

    点击上方 机器学习与生成对抗网络 关注 星标 获取有趣 好玩的前沿干货 2019 cvpr Pluralistic Image Completion https arxiv xilesou top pdf 1903 04227 pdf ht
  • 使用IO流对文件进行读取功能

    对于文件的读取可以用字符流也可以用字节流 下面整理了一份利用字节读流对本地文件进行读取 1 实现思路 第一步 选择文件 实例化一个文件File 在File的构造里放上你要读取的文件路径 文件路径的斜杠需要用转义符进行处理 如果文件在项目的根
  • 为什么 Java 中只有值传递?

    开始之前 我们先来搞懂下面这两个概念 形参 实参 值传递 引用传递 形参 实参 方法的定义可能会用到 参数 有参的方法 参数在程序语言中分为 实参 实际参数 用于传递给函数 方法的参数 必须有确定的值 形参 形式参数 用于定义函数 方法 接
  • 管理conda environments

    欢迎关注 生信修炼手册 environments作为conda的核心组件 用于封装相互独立的软件环境 通过在不同的environment中安装packages 来实现不同软件的相互独立 通过在不同的environments之间进行切换 从而
  • C语言 实现学生管理系统(手把手教学)

    学生管理系统怎么实现 首先要对问题能分析出框架来 这样在之后书写功能时就会对所需要的东西有一个清晰的认知 那么 管理系统的任务就是 能删除 查找和修改学生信息 能进行排序 能打印信息 这些都是最基本的功能 把这些功能框架写在一个c源文件里
  • HDU1007(Quoit Design)

    Quoit Design 题目传送门 Problem Description Have you ever played quoit in a playground Quoit is a game in which flat rings ar
  • 浅谈Javac编译原理

    一 javac是什么 1 javac是一种编译器 能够将一种语言规范转化成另外一种语言规范 2 javac的任务就是将Java源代码转化成JVM能够识别的一种语言 Java字节码 这种字节码不是针对某种机器 某种平台的 二 javac编译器
  • Rethink LSTM&GRU

    LSTM 设计思想 姑且不看偏置 W W W 和 U U U 是加权的矩阵 写模型的时候用 nn Linear in dim out dim 就成
  • 02Linux下使用libcurl(C语言)来实现http请求(数据保存至内存)(这里可以让你深入了解realloc函数)

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