使用 C/C++ 调用 libcurl 调试消息
在使用 C/C++ 调用 libcurl
进行 HTTP 请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试。libcurl
提供了多种方法来捕获和输出这些信息,本文介绍具体的使用方式。
1. libcurl 调试工具简介
libcurl
是一个功能强大的库,用于在 C/C++ 中实现 HTTP 请求(支持 GET、POST、PUT 等方法)。为了调试请求和响应信息,libcurl
提供了以下功能:
- 启用详细日志输出: 使用
CURLOPT_VERBOSE
打印所有传输信息。 - 自定义调试回调函数: 使用
CURLOPT_DEBUGFUNCTION
捕获并处理调试日志。 - 输出请求头和请求体: 使用
CURLINFO_HEADER_OUT
和CURLOPT_POSTFIELDS
输出完整的请求。 - 捕获响应内容: 使用
CURLOPT_WRITEFUNCTION
将服务器响应保存到变量中。
2. 输出请求消息
-
使用
CURLOPT_VERBOSE
CURLOPT_VERBOSE
是最简单的调试工具,通过设置该选项为 1L
,可以让 libcurl
输出详细的传输信息,包括请求头和请求体:
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
输出内容示例如下:
> POST /api HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Content-Length: 29
>
* upload completely sent off: 29 out of 29 bytes
-
使用
CURLOPT_DEBUGFUNCTION
如果需要对调试信息进行更多控制,可以使用 CURLOPT_DEBUGFUNCTION
自定义处理逻辑,例如将日志保存到文件或字符串中。
以下是自定义调试回调函数的代码:
#include <iostream>
#include <string>
#include <curl/curl.h>int DebugCallback(CURL* handle, curl_infotype type, char* data, size_t size, void* userptr) {std::string* log = static_cast<std::string*>(userptr);if (type == CURLINFO_HEADER_OUT) {log->append("[REQUEST HEADERS]:\n");log->append(data, size);} else if (type == CURLINFO_DATA_OUT) {log->append("[REQUEST BODY]:\n");log->append(data, size);}return 0;
}
3. 输出响应消息
为了捕获服务器的响应,可以使用 CURLOPT_WRITEFUNCTION
将响应保存到变量中:
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {size_t totalSize = size * nmemb;userp->append((char*)contents, totalSize);return totalSize;
}
在配置 CURL 选项时,添加:
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);
4. 完整代码示例
以下是一个完整的示例,展示如何使用 libcurl
发送 HTTPS POST 请求,并输出请求和响应的详细信息。
#include <iostream>
#include <string>
#include <curl/curl.h>// 自定义调试回调函数
int DebugCallback(CURL* handle, curl_infotype type, char* data, size_t size, void* userptr) {std::string* log = static_cast<std::string*>(userptr);if (type == CURLINFO_HEADER_OUT) {log->append("[REQUEST HEADERS]:\n");log->append(data, size);} else if (type == CURLINFO_DATA_OUT) {log->append("[REQUEST BODY]:\n");log->append(data, size);}return 0;
}// 回调函数:接收服务器的响应数据
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {size_t totalSize = size * nmemb;userp->append((char*)contents, totalSize);return totalSize;
}int main() {CURL* curl = curl_easy_init();if (!curl) {std::cerr << "Failed to initialize CURL!" << std::endl;return 1;}const std::string url = "https://example.com/api";const std::string jsonData = R"({"key1":"value1", "key2":"value2"})";std::string responseString;std::string debugLog; // 用于存储调试日志struct curl_slist* headers = nullptr;headers = curl_slist_append(headers, "Content-Type: application/json");// 设置 CURL 选项curl_easy_setopt(curl, CURLOPT_URL, url.c_str());curl_easy_setopt(curl, CURLOPT_POST, 1L);curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);// 启用调试功能curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, DebugCallback);curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &debugLog);// 执行请求CURLcode res = curl_easy_perform(curl);if (res != CURLE_OK) {std::cerr << "CURL error: " << curl_easy_strerror(res) << std::endl;} else {std::cout << "Response: " << responseString << std::endl;}// 输出调试日志std::cout << "\n===== Debug Log =====\n" << debugLog << std::endl;curl_easy_cleanup(curl);curl_slist_free_all(headers);return 0;
}
5. 编译和运行
-
确保已安装
libcurl
。 在 Ubuntu 上安装:sudo apt-get install libcurl4-openssl-dev
-
使用以下命令编译代码:
g++ -o post_debug post_debug.cpp -lcurl
-
运行程序:
./post_debug
6. 输出示例
程序运行后,会输出请求和响应信息,例如:
调试日志
===== Debug Log =====
[REQUEST HEADERS]:
POST /api HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 29[REQUEST BODY]:
{"key1":"value1", "key2":"value2"}
响应内容
Response: {"status":"success","message":"Data received"}
总结
通过启用 CURLOPT_VERBOSE
或自定义 CURLOPT_DEBUGFUNCTION
,可以轻松查看 libcurl
的请求消息(包括请求头和请求体)。结合响应回调函数,能完整调试 HTTP 请求和服务器返回的内容。这些工具对于开发和调试网络程序非常有用!
相关文章:

使用 C/C++ 调用 libcurl 调试消息
在使用 C/C 调用 libcurl 进行 HTTP 请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试。libcurl 提供了多种方法来捕获和输出这些信息,本文介绍具体的使用方式。 1. libcurl 调试工具简介 libcurl 是…...

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》030-自定义组件的插槽Mixin
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主&…...

大一计算机的自学总结:异或运算
前言 异或运算这个操作看上去很匪夷所思,实际上作用非常大。 一、异或运算的性质 1.异或运算就是无进位相加。 2.满足交换律、结合律。 3.0^nn,n^n0。 4.若集合B为集合A子集,集合A异或和为x,集合B异或和为y,则集…...

通过protoc工具生成proto的pb.go文件以及使用protoc-go-inject-tag工具注入自定义标签
1.ProtoBuf认识,安装以及用法 参考:[golang 微服务] 3. ProtoBuf认识,安装以及golang 中ProtoBuf使用 2. 使用protoc-go-inject-tag工具注入自定义标签 这里有一个案例: syntaxproto3; package test;option go_package ".;test";message MyMessage {int6…...

C语言练习(29)
13个人围成一圈,从第1个人开始顺序报号1、2、3。凡报到“3”者退出圈子,找出最后留在圈子中的人原来的序号。本题要求用链表实现。 #include <stdio.h> #include <stdlib.h>// 定义链表节点结构体 typedef struct Node {int num;struct Nod…...

Android实训九 数据存储和访问
实训9 数据存储和访问 一、【实训目的】 1、 SharedPreferences存储数据; 2、 借助Java的I/O体系实现文件的存储, 3、使用Android内置的轻量级数据库SQLite存储数据; 二、【实训内容】 1、实现下图所示的界面,实现以下功能: 1ÿ…...

实验一---典型环节及其阶跃响应---自动控制原理实验课
一 实验目的 1.掌握典型环节阶跃响应分析的基本原理和一般方法。 2. 掌握MATLAB编程分析阶跃响应方法。 二 实验仪器 1. 计算机 2. MATLAB软件 三 实验内容及步骤 利用MATLAB中Simulink模块构建下述典型一阶系统的模拟电路并测量其在阶跃响应。 1.比例环节的模拟电路 提…...

SOME/IP--协议英文原文讲解2
前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.1 Speci…...

matlab中,fill命令用法
在 MATLAB 中,fill 命令用于创建填充多边形的图形对象。使用 fill 可以在二维坐标系中绘制填充的区域,通常用于绘制图形的背景或显示数据分布。 基本语法 fill(X, Y, C)X 和 Y 是同样长度的向量,定义了多边形的顶点坐标。C 是颜色࿰…...

【Linux】Linux C判断两个IPv6地址是否有包含关系
功能说明 要判断两个 IPv6 地址是否具有包含关系,包括前缀的比较,可以通过以下步骤实现: 解析 IPv6 地址和前缀:将两个 IPv6 地址和它们的前缀长度解析为二进制形式。生成掩码:根据前缀长度生成掩码。按位比较&#…...

【玩转全栈】----Django基本配置和介绍
目录 Django基本介绍: Django基本配置: 安装Django 创建项目 创建app 注册app Django配置路由URL Django创建视图 启动项目 Django基本介绍: Django是一个开源的、基于Python的高级Web框架,旨在以快速、简洁的方式构建高质量的Web…...

mysql 学习6 DML语句,对数据库中的表进行 增 删 改 操作
添加数据 我们对 testdatabase 数据中 的 qqemp 这张表进行 增加数据,在这张表 下 打开 命令行 query console 在 软件中就是打开命令行的意思 可以先执行 desc qqemp; 查看一下当前表的结构。 插入一条数据 到qqemp 表,插入时要每个字段都有值 insert…...

自动化运维在云环境中的完整实践指南
随着云计算的普及,越来越多的企业将业务迁移到云上。云环境的高动态性和复杂性使得传统的手动运维方式难以应对,自动化运维成为提升效率、降低成本、保障系统稳定性的关键。本文将详细介绍如何在云环境中实施自动化运维,涵盖工具选择、实施步骤和最佳实践。 © ivwdcwso…...

一分钟搭建promehteus+grafana+alertmanager监控平台
为什么要自己搭建一个监控平台 平时进行后端开发,特别是微服务的后端可开发,一定少不了对接监控平台,但是平时进行一些小功能的测试又没有必要每次都手动安装那么多软件进行一个小功能的测试,这里我使用docker-compose搭建了一个…...

【10.2】队列-设计循环队列
一、题目 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普…...

设置jmeter界面图标字体大小
设置jmeter界面图标字体大小 方法:点击“选项” -> 点击放大、缩小。(可进行全局的菜单、左侧目录结构树、元件界面显示等字体图标的放大、缩小。)...

Xposed-Hook
配置 Xposed 模块的 AndroidManifest.xml: <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"package"your.package.name"><applicationandr…...

设计模式Python版 原型模式
文章目录 前言一、原型模式二、原型模式示例三、原型管理器 前言 GOF设计模式分三大类: 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式:关注类和对…...

QT:图像上绘制图形
需求描述 1、展示一张图像 2、在图像上可以使用数据绘制图像:矩形、不规则图形、线条 3、有按键可以选择 概要设计 规划布局如下 1、左边是Qlabel 用于展示图片 2、右边是三个按钮 具体实现 1、 首先设计 UI 界面,对控件进行布局 在 mainwindow.u…...

GPU上没程序在跑但是显存被占用
原因:存在僵尸线程,运行完但是没有释放内存 查看僵尸线程 fuser -v /dev/nvidia*关闭僵尸线程 pkill -9 -u 用户名 程序名 举例:pkill -9 -u grs python参考:https://blog.csdn.net/qq_40206371/article/details/143798866...

wordpress代码结构解析
WordPress 是一个基于 PHP 和 MySQL 的开源内容管理系统(CMS),广泛用于构建网站和博客。要解析 WordPress 代码,首先需要了解其核心结构、主要文件和常用的函数。以下是 WordPress 代码解析的基本指南: --- ### 1. *…...

【Unity3D】实现2D小地图效果
目录 一、玩家脚本Player 二、Canvas组件设置 三、小地图相关 四、GameLogicMap脚本修改 基于:【Unity3D】Tilemap俯视角像素游戏案例-CSDN博客 2D玩家添加Dotween移动DOPath效果,移动完成后进行刷新小地图(小地图会顺便刷新大地图&…...

关联传播和 Python 和 Scikit-learn 实现
文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数:集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…...

https数字签名手动验签
以bing.com 为例 1. CA 层级的基本概念 CA 层级是一种树状结构,由多个层级的 CA 组成。每个 CA 负责为其下一层级的实体(如子 CA 或终端实体)颁发证书。层级结构的顶端是 根 CA(Root CA),它是整个 PKI 体…...

LeetCode:62.不同路径
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:62.不同路径 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” &…...

如果我想设计一款复古风格的壁纸,应该选什么颜色?
设计复古风格的壁纸时,选择合适的颜色是营造怀旧和经典氛围的关键。复古风格通常使用一些温暖、柔和且带有岁月痕迹的色调。以下是一些适合复古风格壁纸的颜色选择和搭配建议: 一、复古风格的主色调 棕色系: 特点:棕色是复古风格的…...

【数据结构】树的基本:结点、度、高度与计算
树是数据结构中一种重要的非线性结构,广泛应用于计算机科学的各个领域,例如文件系统、数据库索引、编译器等。理解树的各种性质,如结点数、度、高度等,对于解决实际问题至关重要。 本文将会探讨树的基本概念,以及给出几…...

【Pytest】生成html报告中,中文乱码问题解决方案
链接上一篇文章:https://blog.csdn.net/u013080870/article/details/145369926?spm1001.2014.3001.5502 中文乱码问题,python3,Python3.7后,还一个文件就是result.py 因为中文可以在内容中,也可能在文件名,类名&…...

week08_文本匹配任务
1、文本匹配任务概述 狭义: 给定一组文本,判断其是否语义相似 今天天气不错 match 今儿个天不错呀 √ 今天天气不错 match 你的代码有bug 以分值形式给出相似度 今天天气不错 match 今儿个天不错呀 0.9 今天天气不错 match…...

JUC--ConcurrentHashMap底层原理
ConcurrentHashMap底层原理 ConcurrentHashMapJDK1.7底层结构线程安全底层具体实现 JDK1.8底层结构线程安全底层具体实现 总结JDK 1.7 和 JDK 1.8实现有什么不同?ConcurrentHashMap 中的 CAS 应用 ConcurrentHashMap ConcurrentHashMap 是一种线程安全的高效Map集合…...