当前位置: 首页 > news >正文

由浅入深C系列五:使用libcurl进行基于http get/post模式的C语言交互应用开发

使用libcurl进行基于http get/post模式的C语言交互应用开发

  • 简介
  • 环境准备
  • 在线资源
  • 示例代码
  • 测试调用
  • 运行结果

简介

大多数在linux下的开发者,都会用到curl这个命令行工具。对于进行restful api的测试等,非常方便。其实,这个工具还提供了一个C的开发库,可以很方便的在C语言开发环境下完成基于http的请求和响应交互,高效的开发基于http/smtp等的网络应用程序

/* 2023-08-14 更新宏定义 1. 使用可变参数,支持多项输出; 2. 去除Z中默认加上的双引号; 
*/
#define X_LOG_DEBUG(Z, X...) \printf("[%s %s] [%s.%d] [%s] [DEBUG] " Z "\n", __DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__, ##X)

环境准备

下载并安装curl的开发包

yum install libcurl-devel.x86_64

在线资源

开发过程中主要参考CURL官方介绍及API参考文档 | link

示例代码

多余的话就不多说了,直接上示例代码,通过代码中的注释来说明开发过程。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../include/xhttp.h"/*
-  这个是一个回调函数,主要用于curl在执行过程中,当有被请求的数据到达时,被调用来向-curl_easy_setopt设置的chunk中写入数据。这个回调函数在curl_easy_perform执行完成前会被调用多次。当执行完成后,从chunk中取出这次交互返回的数据。
*/
static size_t cb_write_data(void *data, size_t size, size_t nmemb, void *clientp)
{size_t realsize = size * nmemb;http_response *mem = (http_response *)clientp;char *ptr = realloc(mem->response, mem->size + realsize + 1);if(ptr == NULL)return 0;  /* out of response_st! */mem->response = ptr;memcpy(&(mem->response[mem->size]), data, realsize);mem->size += realsize;mem->response[mem->size] = 0;return realsize;
}/*这个是向外发布的一个函数,调用的方式示例如下:char* payload = "{\"code\":\"\",\"codeUuid\":\"\",\"loginName\":\"user@domain\",\"loginPwd\":\"xxxxxxxx\"}";http_response *resp = http_post("https://local.domain/admin-api/session/login", NULL, payload);使用完返回数据后,记得释放resp->reesponse,避免内存漏。
*/
http_response* http_post(char* url, char* token, char* payload) 
{http_response chunk = {0};/* 设置curl上下文,对curl实例进行初始化 */curl_global_init(CURL_GLOBAL_ALL);CURL *curl = curl_easy_init();CURLcode res;if(curl) {X_LOG_DEBUG("%s", "libcurl curl_easy_setopt start ...");/* 设置curl各个参数: 请求地址 */curl_easy_setopt(curl, CURLOPT_URL, url);/* 设置curl各个参数: 请求方式为post */curl_easy_setopt(curl, CURLOPT_POST, 1L);/* 设置curl各个参数: http中的请求头部分的内容 */X_LOG_DEBUG("%s", "libcurl curl_easy_setopt CURLOPT_HTTPHEADER start ...");struct curl_slist *list = {0};list = curl_slist_append(NULL, "Content-Type: application/json;charset=utf8");list = curl_slist_append(list, "routeurl: /project/project-list");/* 设置curl各个参数: 可选部分,如果请求中要求token,可以设置上 */if (token != NULL){char* x_access_token_str = (char*)malloc( MAX_UTMP_TOKEN_SIZE );sprintf(x_access_token_str, "x-access-token: %s", token);X_LOG_DEBUG("%s", x_access_token_str);list = curl_slist_append(list, x_access_token_str);}curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);X_LOG_DEBUG("%s", "libcurl curl_easy_setopt CURLOPT_USERAGENT start ...");/* some servers do not like requests that are made without a user-agent field, so we provide one */curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0");/* 设置curl各个参数: http的请求体部分,主要是请求中携带的数据 *//* POST data */X_LOG_DEBUG("%s", "libcurl curl_easy_setopt CURLOPT_POSTFIELDSIZE/CURLOPT_POSTFIELDS start ...");X_LOG_DEBUG("request body data is:%s", payload);X_LOG_DEBUG("request body len is:%d", strlen(payload));/* size of the POST data */curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(payload));/* pass in a pointer to the data - libcurl will not copy */curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);/* 设置curl各个参数: 重要部分,设置了返回值的回调函数和返回值的内存放置区域 *//* RECEIVE DATA */X_LOG_DEBUG("%s", "libcurl curl_easy_setopt CURLOPT_WRITEFUNCTION/CURLOPT_WRITEDATA start ...");/* send all data to this function  */curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb_write_data);/* we pass our 'chunk' struct to the callback function */curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);X_LOG_DEBUG("%s", "libcurl curl_easy_setopt successfully complete ...");/* 执行curl请求,并获取返回值:CURLE_OK,表示执行成功 */X_LOG_DEBUG("%s", "libcurl curl_easy_perform start ...");res = curl_easy_perform(curl);X_LOG_DEBUG("%s", "libcurl curl_easy_perform successfully complete ...");if(res != CURLE_OK) {fprintf(stderr, "curl_easy_perform() is failed: %s", curl_easy_strerror(res));curl_slist_free_all(list); /* free the list again */curl_easy_cleanup(curl);} else {/* 处理curl返回的数据 */X_LOG_DEBUG("chunk size %d", chunk.size);http_response response = {0};response.response = (char*)malloc(1048576*5);memset(response.response, 0, chunk.size+1);memcpy(response.response, chunk.response, chunk.size+1);response.size = chunk.size;/* remember to free the buffer */free(chunk.response);curl_slist_free_all(list); /* free the list again */ curl_global_cleanup();return &response;}} 
}

引用的头文件如下:

#ifndef __X_HTTP_H__
#define __X_HTTP_H__#include <stdlib.h>
#include <curl/curl.h>
/* 更新宏定义 1. 使用可变参数,支持多项输出; 2. 去除Z中默认加上的双引号; */
#define X_LOG_DEBUG(Z, X...) \printf("[%s %s] [%s.%d] [%s] [DEBUG] " Z "\n", __DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__, ##X)#define MAX_UTMP_TOKEN_SIZE 8192typedef struct http_response_s {char *response;size_t size;
} http_response;typedef struct http_request_s {char *request;size_t size;
} http_request;http_response* http_post(char* url, char* token, char* payload);#endif

测试调用

int main(int argc, char** argv) {char* payload = "{\"code\":\"\",\"codeUuid\":\"\",\"loginName\":\"user@domain\",\"loginPwd\":\"xxxxxxxx\"}";http_response *resp = http_post("https://local.domain/admin-api/session/login", NULL, payload);printf("http_response [%d] is: %s\n", resp->size, resp->response);char *tokenVal = strstr(resp->response, "xaccessToken");int end = strlen(tokenVal);*(tokenVal + end-2) = 0;char** token_arr;__strtok_r(tokenVal, ":", token_arr);char* replacementKey = strtrim(token_arr[0], '\"');exit(0)
}

运行结果

[Aug 11 2023 10:20:02] [src/xhttp.c.37] [http_post] [DEBUG] "libcurl curl_easy_setopt start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.42] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_HTTPHEADER start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.55] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_USERAGENT start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.61] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_POSTFIELDSIZE/CURLOPT_POSTFIELDS start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.62] [http_post] [DEBUG] "request body data is:{"code":"","codeUuid":"","loginName":"user@domain","loginPwd":"xxxxxxxx"}"
[Aug 11 2023 10:20:02] [src/xhttp.c.63] [http_post] [DEBUG] "request body len is:75"
[Aug 11 2023 10:20:02] [src/xhttp.c.70] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_WRITEFUNCTION/CURLOPT_WRITEDATA start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.76] [http_post] [DEBUG] "libcurl curl_easy_setopt successfully complete ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.79] [http_post] [DEBUG] "libcurl curl_easy_perform start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.81] [http_post] [DEBUG] "libcurl curl_easy_perform successfully complete ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.90] [http_post] [DEBUG] "chunk size 6693"

相关文章:

由浅入深C系列五:使用libcurl进行基于http get/post模式的C语言交互应用开发

使用libcurl进行基于http get/post模式的C语言交互应用开发 简介环境准备在线资源示例代码测试调用运行结果 简介 大多数在linux下的开发者&#xff0c;都会用到curl这个命令行工具。对于进行restful api的测试等&#xff0c;非常方便。其实&#xff0c;这个工具还提供了一个C…...

高效实用小工具之Everything

一&#xff0c;简介 有时候我们电脑文件较多时&#xff0c;想快速找到某个文件不是一件容易的事情&#xff0c;实用windows自带的搜素太耗时&#xff0c;效率不高。今天推荐一个用来搜索电脑文件的小工具——Everything&#xff0c;本文将介绍如何安装以及使用everything&…...

【Unity每日一记】关于物体(敌方)检测—(向量点乘相关)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…...

Elasticsearch-查询

一、查询和过滤 1.1 相关性分数 &#xff1a;_score 默认情况下&#xff0c;Elasticsearch 按相关性得分对匹配的搜索结果进行排序&#xff0c;相关性得分衡量每个文档与查询的匹配程度。 相关性分数是一个正浮点数&#xff0c;在搜索的数据字段中返回。_score越高&#xff0…...

首发 | FOSS分布式全闪对象存储系统白皮书

一、 产品概述 1. 当前存储的挑战 随着云计算、物联网、5G、大数据、人工智能等新技术的飞速发展&#xff0c;数据呈现爆发式增长&#xff0c;预计到2025年中国数据量将增长到48.6ZB&#xff0c;超过80%为非结构化数据。 同时&#xff0c;数字经济正在成为我国经济发展的新…...

Java反射获取所有Controller和RestController类的方法

Java反射获取所有Controller和RestController类的方法 引入三方反射工具Reflections <dependency><groupId>org.reflections</groupId><artifactId>reflections</artifactId><version>0.10.2</version> </dependency>利用反…...

设计模式--策略模式

目录 一.场景 1.1场景 2.2 何时使用 2.3个人理解 二. 业务场景练习 2.1业务: 2.2具体实现 2.3思路 三.总结 3.1策略模式的特点&#xff1a; 3.2策略模式优点 3.3策略模式缺点 一.场景 1.1场景 许多相关的类仅仅是行为有异&#xff0c;也就是说业务代码需要根据场景不…...

VSCode使用SSH无密码连接Ubuntu

VSCode使用SSH无密码连接Ubuntu 前提条件&#xff1a; 1. 能够正常使用vscode的Remote-ssh连接Ubuntu 2. Ubuntu配置静态ip&#xff08;否则经常需要修改Remote-ssh的配置文件里的IP&#xff09; 1. windows下 打开Win下的PowerShell&#xff0c;生成公钥和私钥 ssh-keygen…...

通过版本号控制强制刷新浏览器或清空浏览器缓存

背景介绍 在我们做 web 项目时&#xff0c;经常会遇到一个问题就是&#xff0c;需要 通知业务人员&#xff08;系统用户&#xff09;刷新浏览器或者清空浏览器 cookie 缓存的情况。 而对于用户而言&#xff0c;很多人一方面不懂如何操作&#xff0c;另一方面由于执行力问题&am…...

Redis系列(二):深入解读Redis的两种持久化方式

博客地址&#xff1a;blog.zysicyj.top Redis为什么要引入持久化机制 Redis引入持久化机制是为了解决内存数据库的数据安全性和可靠性问题。虽然内存数据库具有高速读写的优势&#xff0c;但由于数据存储在内存中&#xff0c;一旦服务器停止或崩溃&#xff0c;所有数据将会丢失…...

CNN之图像识别

文章目录 1. 图像识别1.1 模式识别1.2 图像识别的过程1.3 图像识别的应用 2. 深度学习发展2.1 深度学习为何崛起2.2 分类与检测2.3 常见的卷积神经网络 3. VGG3.1 VGG163.2 VGG16的结构&#xff1a;3.3 使用卷积层代替全连接3.4 1*1卷积的作用3.5 VGG16代码示例 4. 残差模型-Re…...

nvcc not found

检查cuda 安装成功 nvidia-smiCommand ‘nvcc’ not found, apt install nvidia-cuda-toolkitnvcc fatal : No input files specified&#xff1b; use option --help for more information # 注意是大写 V nvcc -V export PATH"/usr/local/cuda/bin:$PATH" expor…...

pdf怎么转换成jpg图片?这几个转换方法了解一下

pdf怎么转换成jpg图片&#xff1f;转换PDF文件为JPG图片格式在现代工作中是非常常见的需求&#xff0c;比如将PDF文件中的图表、表格或者图片转换为JPG格式后使用在PPT演示、网页设计等场景中。 【迅捷PDF转换器】是一款非常实用的工具&#xff0c;可以将PDF文件转换成多种不同…...

六轴机械臂码垛货物堆叠仿真

六轴机械臂码垛货物堆叠仿真 1、建立模型与仿真 clear,clc,close all addpath(genpath(.)) %建立模型参数如下&#xff1a; L(1) Link( d, 0.122, a , 0 , alpha, pi/2,offset,0); L(2) Link( d, 0.019 , a ,0.408 , alpha, 0,offset,pi/2); L(3) Link( d, …...

text-decoration 使用

text-decoration text-decoration 用于设置文本上的装饰性线条的外观。 它是 text-decoration-line、text-decoration-style、text-decoration-color 和text-decoration-thickness的缩写。 text-decoration: underline wavy red;text-decoration-line 设置文本装饰类型 可以…...

linux shell快速入门

linux shell快速入门 0 、前置1、简单使用 0 、前置 一安装linux的虚拟环境 1、简单使用 1、新建/usr/shell目录 2、新建hello.sh 文件 3、编写脚本文件# !/bin/bashecho "hello world"查看是否具备执行权限 新增执行权限 chomd x hello.sh执行hello.sh文件 /b…...

【Spring源码】小白速通解析Spring源码,从0到1,持续更新!

Spring源码 参考资料 https://www.bilibili.com/video/BV1Tz4y1a7FM https://www.bilibili.com/video/BV1iz4y1b75q bean的生命周期 bean–>推断构造方法&#xff08;默认是无参构造&#xff0c;或指定的构造方法&#xff09;–>实例化成普通对象&#xff08;相当于ne…...

Unity 鼠标实现对物体的移动、缩放、旋转

文章目录 1. 代码2. 测试场景 1. 代码 using UnityEngine;public class ObjectManipulation : MonoBehaviour {// 缩放比例限制public float MinScale 0.2f;public float MaxScale 3.0f;// 缩放速率private float scaleRate 1f;// 新尺寸private float newScale;// 射线pri…...

67Class 的基本语法

Class 的基本语法 类的由来[constructor() 方法](https://es6.ruanyifeng.com/#docs/class#constructor() 方法)类的实例实例属性的新写法取值函数&#xff08;getter&#xff09;和存值函数&#xff08;setter&#xff09;属性表达式[Class 表达式](https://es6.ruanyifeng.c…...

企业数字化转型:无形资产占比测算(2007-2021年)

在本次数据中&#xff0c;参考张永珅老师的做法&#xff0c;利用无形资产占比测算数字化转型程度。 一、数据介绍 数据名称&#xff1a;企业数字化转型&#xff1a;无形资产占比 数据年份&#xff1a;2007-2021年 样本数量&#xff1a;32960条 数据说明&#xff1a;包括数…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...