【C++】C++使用libcurl做HttpClient

2023-05-16

当使用C++做HTTP客户端时,目前通用的做法就是使用libcurl。其官方网站的地址是http://curl.haxx.se/,该网站主要提供了Curl和libcurl。Curl是命令行工具,用于完成FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP的命令的请求及接收回馈。libcurl提供给开发者,用于使用C++跨平台的开发各种网络协议的请求及响应。里面的文档非常齐全,不过都是英文的。

本文提供最简单的demo使用libcurl开发HttpClient。主要包括同步的HTTP GET、HTTP POST、HTTPS GET、HTTPS POST。

下载libcurl包,如果使用Linux平台,建议下载源文件编译;如果使用Windows平台,建议下载Win32 - MSVC,下载地址是:http://curl.haxx.se/download.html
#ifndef __HTTP_CURL_H__  
#define __HTTP_CURL_H__  

#include <string>  

class CHttpClient  
{  
public:  
    CHttpClient(void);  
    ~CHttpClient(void);  

public:  
    /** 
    * @brief HTTP POST请求 
    * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com 
    * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&… 
    * @param strResponse 输出参数,返回的内容 
    * @return 返回是否Post成功 
    */  
    int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);  

    /** 
    * @brief HTTP GET请求 
    * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com 
    * @param strResponse 输出参数,返回的内容 
    * @return 返回是否Post成功 
    */  
    int Get(const std::string & strUrl, std::string & strResponse);  

    /** 
    * @brief HTTPS POST请求,无证书版本 
    * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com 
    * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&… 
    * @param strResponse 输出参数,返回的内容 
    * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性. 
    * @return 返回是否Post成功 
    */  
    int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);  

    /** 
    * @brief HTTPS GET请求,无证书版本 
    * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com 
    * @param strResponse 输出参数,返回的内容 
    * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性. 
    * @return 返回是否Post成功 
    */  
    int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);  

public:  
    void SetDebug(bool bDebug);  

private:  
    bool m_bDebug;  
};  

#endif

#include "chttpclient.h"
#include "curl/curl.h"
#include <string>

CHttpClient::CHttpClient(void) :
m_bDebug(false)
{

}

CHttpClient::~CHttpClient(void)
{

}

static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
    if(itype == CURLINFO_TEXT)
    {
        //printf("[TEXT]%s\n", pData);
    }
    else if(itype == CURLINFO_HEADER_IN)
    {
        printf("[HEADER_IN]%s\n", pData);
    }
    else if(itype == CURLINFO_HEADER_OUT)
    {
        printf("[HEADER_OUT]%s\n", pData);
    }
    else if(itype == CURLINFO_DATA_IN)
    {
        printf("[DATA_IN]%s\n", pData);
    }
    else if(itype == CURLINFO_DATA_OUT)
    {
        printf("[DATA_OUT]%s\n", pData);
    }
    return 0;
}

static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
    std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
    if( NULL == str || NULL == buffer )
    {
        return -1;
    }

    char* pData = (char*)buffer;
    str->append(pData, size * nmemb);
    return nmemb;
}

int CHttpClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_PROXY, "proxy.xxx.com:8080");//设置代理
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    /**
    * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
    * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
    */
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    if(NULL == pCaPath)
    {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
    }
    else
    {
        //缺省情况就是PEM,所以无需设置,另外支持DER
        //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    }
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    if(NULL == pCaPath)
    {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
    }
    else
    {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    }
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

///////////////////////////////////////////////////////////////////////////////////////////////

void CHttpClient::SetDebug(bool bDebug)
{
    m_bDebug = bDebug;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】C++使用libcurl做HttpClient 的相关文章

随机推荐

  • 游戏开发流程和部分分工

    http blog csdn net njhua123 archive 2009 11 23 4859662 aspx 原创 游戏开发流程和部分分工 收藏 游戏开发流程和部分分工 流程 xff1a 调研 开发 测试 运营 xff08 我们公
  • C++以http接口推送json流和图片流

    一 C 43 43 推送json流 C 43 43 代码 xff1a span class token comment span span class token comment a single threaded multi client
  • subprocess.Popen执行程序以及关闭进程

    python中有一个很好用的方式来开启进程 xff0c 即subprocess Popen 正常来说 xff0c 如果subprocess Popen要执行的脚本是一个死循环的脚本 xff0c 那么我们就需要手动的来关闭这个脚本 xff0c
  • 【Simulink教程案例16】基于simulink的LDPC编译码+16QAM调制解调通信系统性能仿真——输出误码和星座图

    欢迎订阅 FPGA MATLAB SIMULINK系列教程 Simulink教程目录 本课程学习成果预览 目录 1 软件版本 2 LDPC编译码理论简介
  • C++头文件定义全局函数或类成员函数

    C 43 43 头文件定义全局函数或类成员函数 你可能很熟悉C C 43 43 的声明定义规则 xff1a 头文件中声明变量和函数 xff0c 源文件中定义变量和函数 在头文件中定义变量和函数会导致 重定义 xff0c 因为包含该头文件的不
  • 分享几种锂电池均衡电路的工作原理

    新能源的发展 xff0c 电动汽车发展 xff0c 都会用到能量密度比更高的锂电池 xff0c 而锂电池串联使用过程中 xff0c 为了保证电池电压的一致性 xff0c 必然会用到电压均衡电路 在这几年的工作过程中 xff0c 用到过几种电
  • 思岚科技激光雷达全面升级:RPLIDAR A1仅需900元,A2测距提升至8米

    思岚科技自2009年着手研发低成本激光雷达 xff0c 2014年面向全球推出了第一代产品RPLIDAR A1 xff0c 在6米测量半径内 xff0c 可完成每秒2000次激光测距 自推出至今 xff0c 已累计使用用户达上千家 时隔两年
  • 【产品评测】用RPLIDAR A2搭建gmapping

    以我自己的小车mrobot为例 1 硬件环境 xff1a mrobot小车 xff08 采用turtlebot create协议 xff0c 可以用turtlebot xff09 rplidar激光雷达 2 rplidar包下载 git c
  • 如何利用RPLIDAR A2进行多点触摸应用

    1 RPLidar激光雷达套件 2 RPlidar multi touch SDK 请点击 这里 下载 注意事项 注意 此SDK仅适用于RPLiDAR A2 型号 xff0c 其他型号暂不支持 xff0c 请知悉 1 请确保USB线不宜过长
  • ROS机器人编程学习(五)——ROS命令3

    第5章 ROS命令 本章主要讲解了ROS下的常用操作命令 xff0c 包括shell命令 执行命令 信息命令 catkin命令 功能包命令 由于这一章内容实在太多了 xff0c 因此博客分三节进行学习记录 本文主要记录catkin命令和功能
  • 什么是哈希码?它的作用是什么?

    哈希值 哈希算法将任意长度的二进制值映射为固定长度的较小二进制值 xff0c 这个小的二进制值称为哈希值 哈希值是一段数据唯一且极其紧凑的数值表示形式 如果散列一段明文而且哪怕只更改该段落的一个字母 xff0c 随后的哈希都将产生不同的值
  • 队列数据结构详解

    1 队列既可以用链表实现 xff0c 也可以用顺序表实现 跟栈相反的是 xff0c 栈一般用顺序表来实现 xff0c 而队列我们常用链表来实现 xff0c 称为链队列 xff0c 它是后入前出 头结点进 xff0c 尾结点出 xff0c 头
  • 数据结构之树的存储结构

    大家可能都知道 xff0c 存储结构有顺序存储结构和链式存储结构 很明显这两个结构不管哪一个 xff0c 都不能很好的表达数这种数据结构 xff0c 所以我们特此在这说一下数的存储结构 用这个树作为例子 xff1a 树的存储结构分为以下几类
  • 收发多径都考虑的情况

    0 完整源码获得方式 订阅MATLAB FPGA教程 xff0c 免得获得教程案例以及任意2份完整源码 收发多径都考虑的情况 clear all close all clc c 61 3e8 f0 61 150e6 载波频率 fd 61 1
  • Linux进程管理命令

    1 ps命令 ps aux xff1a 查看系统中的所有进程 xff0c 使用BS操作系统格式 ps le xff1a 查看系统中的所有进程 xff0c 使用LINUX标准命令格式 选项 xff1a a xff1a 显示一个终端的所有进程
  • C++信号概念

    信号 xff1a 它是操作系统传给进程的中断 xff0c 用来中断程序 xff0c 在Linux系统和Windows系统上可以用ctr 43 c产生中断信号 一 xff1a 穿插一个linux下各个快捷按键的信号区别 xff1a 1 ctr
  • Linux系统编程

    Linux系统中所见皆文件 bin xff1a 所存放二进制可执行文件 boot xff1a 存放开机启动程序 dev xff1a 存放设备文件 home xff1a 存放用户 etc xff1a 用户信息和系统配置文件 lib xff1a
  • Linux系统编程(续)

    静态库制作及使用步骤 xff1a 1 将 c生成 o文件 gcc c add c o add o 2 使用ar工具制作静态库 ar rcs lib自定义库名 a 后面需要的 c文件 3 编译静态库到可执行文件中 gcc test c 自制的
  • keil 提示internal command error和no sw device

    1 使用keil烧录软件的时候 xff0c jlink stlink无法识别到芯片 需要排查的问题 1 xff09 换条线 2 xff09 是不是有程序禁用了Seral Wire xff1a 使用cubeide cubeMX xff0c 容
  • 【C++】C++使用libcurl做HttpClient

    当使用C 43 43 做HTTP客户端时 xff0c 目前通用的做法就是使用libcurl 其官方网站的地址是http curl haxx se xff0c 该网站主要提供了Curl和libcurl Curl是命令行工具 xff0c 用于完