【LibCurl】C++使用libcurl实现HTTP POST和GET、PUT
libcurl简介
libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证
libcurl的官网: http://curl.haxx.se/
库下载地址: https://github.com/curl/curl/releases/tag/curl-7_71_1
libcurl的简单使用
初始化libcurl:
curl_global_init()
函数得到 easy interface型指针:
curl_easy_init()
设置传输选项:
curl_easy_setopt()
设置的传输选项,实现回调函数以完成用户特定任务:
curl_easy_setopt()
函数完成传输任务:
curl_easy_perform()
释放内存:
curl_easy_cleanup()
curl_global_init
CURLcode curl_global_init(long flags);函数只能用一次。(其实在调用curl_global_cleanup 函数后仍然可再用)
如果这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动调用,
所以多线程下最好主动调用该函数以防止在线程中curl_easy_init时多次调用。
注意:虽然libcurl是线程安全的,但curl_global_init是不能保证线程安全的,
所以不要在每个线程中都调用curl_global_init,应该将该函数的调用放在主线程中。
写入此函数避免出现上述风险:
参数:flags
CURL_GLOBAL_ALL //初始化所有的可能的调用。
CURL_GLOBAL_SSL //初始化支持 安全套接字层。
CURL_GLOBAL_WIN32 //初始化win32套接字库。
CURL_GLOBAL_NOTHING //没有额外的初始化。
封装:C++使用libcurl实现HTTP POST和GET
在C++中使用libcurl实现HTTP POST和GET的源码如下:
#include <curl/curl.h>
#include <string>
class HttpConnection {
public:
HttpConnection() {
curl_global_init(CURL_GLOBAL_ALL);
curl_ = curl_easy_init();
}
~HttpConnection() {
curl_easy_cleanup(curl_);
}
bool Post(const std::string& url, const std::string& data, std::string& response) {
if (!curl_) {
return false;
}
// set params
// set curl header
struct curl_slist* header_list = NULL;
// der_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
header_list = curl_slist_append(header_list, "Content-Type:application/json; charset = UTF-8");
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, header_list);
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl_, CURLOPT_POST, 1L);
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl_);
return (res == CURLE_OK);
}
bool Get(const std::string& url, std::string& response) {
if (!curl_) {
return false;
}
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl_, CURLOPT_POST, 0L);
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl_);
return (res == CURLE_OK);
}
private:
CURL* curl_ = nullptr;
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t realsize = size * nmemb;
std::string* str = static_cast<std::string*>(userp);
str->append(static_cast<char*>(contents), realsize);
return realsize;
}
};
这个类中包含了两个公共方法Post和Get,用于实现HTTP的POST和GET请求。
它们接受一个URL参数和可选的请求数据,以及一个用于存储响应的字符串引用。
在使用这个类之前,需要先创建一个实例,并调用Post或Get方法。
如果请求成功,方法会返回true,并将服务器响应存储在传递的response字符串中。
否则,它将返回false,response将保持为空字符串。
扩展,LibCurl 实现 Put 操作
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <check_error.h>
FILE *fp; //定义FILE类型指针
//重写把数据读入上传数据流函数
size_t read_file(void* buff, size_t size, size_t nmemb, void* userp)
{
size_t sizes = fread(buff, size, nmemb, (FILE *)userp);
return sizes;
}
int main(int argc,char **argv)
{
CURLcode res; //easy_handle定义的一些错误码
const char url[2096];
//初始化libcurl
if(argc!=3)
{
printf("please input url and filename");
exit(-1);
}
res = curl_global_init(CURL_GLOBAL_ALL);
if (res != CURLE_OK)
{
printf("init libcurl failed.\n" );
return -1;
}
//获取要上传的文件指针
FILE* r_file = fopen(argv[2], "rb");
if (0 == r_file)
{
printf( "the file %s isnot exit\n",argv[2]);
return -1;
}
CURL* easy_handle;
easy_handle = curl_easy_init();
if (0 == easy_handle)
{
printf( "get a easy_handle handle fail!");
fclose(r_file);
curl_global_cleanup();
curl_easy_cleanup(easy_handle);
return -1;
}
// 获取文件大小
fseek(r_file, 0, 2);
int file_size = ftell(r_file);
rewind(r_file);
curl_easy_setopt(easy_handle, CURLOPT_URL, argv[1]); //获取URL地址
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, 1); //告诉easy_handle是做上传操作
curl_easy_setopt(easy_handle, CURLOPT_READFUNCTION, &read_file); //调用重写的读文件流函数
curl_easy_setopt(easy_handle, CURLOPT_READDATA, r_file); //往read_file()函数中传入用户自定义的数据类型
curl_easy_setopt(easy_handle, CURLOPT_INFILE, r_file); //定位作为上传的输入文件
curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, 1); //打印出具体http协议字段
//curl_easy_setopt(easy_handle, CURLOPT_HEADER, 1);
curl_easy_setopt(easy_handle, CURLOPT_INFILESIZE, file_size); //上传的字节数
//执行设置好的操作
res = curl_easy_perform(easy_handle);
//获取HTTP错误码
int HTTP_flag = 0;
curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE , &HTTP_flag);
//一般清理动作
fclose(r_file);
curl_global_cleanup();
curl_easy_cleanup(easy_handle);
printf("url :%s localfile: %s\n",argv[1],argv[2]);
printf("HTTP_flag is %d\n",HTTP_flag);
// printf( "操作本地文件: file_name url:\n");
//检测HTTP错误码和执行操作结果
if (CURLE_OK != res)
{
printf("failure\n");
return -1;
}
else
{
printf("success\n");
return 0;
}
}
在 StackOverFlow 中有一则关于 Put 操作的问题:https://stackoverflow.com/questions/7569826/send-string-in-put-request-with-libcurl
其中的回答有说:Dont use curl_easy_setopt(curl, CURLOPT_PUT, 1L);
比较好的写法是如此:
curl = curl_easy_init();
if (curl) {
headers = curl_slist_append(headers, client_id_header);
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, request_url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); /* !!! */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_struct); /* data goes here */
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
比较好奇 why 这样,结果查询 LibCurl 官方的资料说:CURLOPT_PUT 已经被弃用了(简单明了,所以正确的使用姿势应该保证是 CURLOPT_UPLOAD Option)
【LibCurl】C++使用libcurl实现HTTP POST和GET、PUT的更多相关文章
- libCURL开源库在VS2010环境下编译安装,配置详解
libCURL开源库在VS2010环境下编译安装,配置详解 转自:http://my.oschina.net/u/1420791/blog/198247 http://blog.csdn.net/su ...
- libcurl安装使用方法-简单实用(摘录)
http://curl.haxx.se/libcurl/c/example.html 官网c例子http://curl.haxx.se/download/curl-7.21.3.tar.gz 下载地址 ...
- linux c libcurl的简单使用(转)
curl是Linux下一个非常著名的下载库,通过这个库,可以很简单的实现文件的下载等操作.看一个简单的例子: #include <curl/curl.h> #include <std ...
- Libcurl笔记二
一: multi与easy接口的不同处The multi interface offers several abilities that the easy interface doesn't. The ...
- 如何编译libcurl
1. Android •1.1配置 •1.2 Make •1.3的参数配置 2.iOS 3.windows 4.关于头文件 注释 本文档介绍了如何为Android,iOS和Windows编译libcu ...
- libcurl的封装,支持同步异步请求,支持多线程下载,支持https
最近在做一个项目,需要用到http get post等 需求分析需要做到同步和异步,异步请求的返回以可选的回调通知的方式进行. 本人以Linux为例,一步一步的来实现. 配置并且编译libcurl我以 ...
- qt5集成libcurl实现tftp和ftp的方法一:搭建环境(五篇文章)
最近使用QT5做一个软件,要求实现tftp和ftp文件传输,使用QT5开发好UI界面等功能,突然发现QT5不直接提供tftp和ftp支持,无奈之下只好找第三方库来间接实现,根据网友的介绍,libcur ...
- Libcurl最初的实现tfp上传和下载功能
研究报告指出的目标是使用libcurl实现ftp文件上传和下载功能 一.Libcurlde简要 Libcurl的而且易于使用的利用url进行文件传输的库. , libcurl当前支持DICT, FIL ...
- Libcurl细说
libcurl教程 原文地址:http://curl.haxx.se/libcurl/c/libcurl-tutorial.html 译者:JGood(http://blog.csdn.net/J ...
- 最全的libcurl库资源整理
C++ 用libcurl库进行http 网络通讯编程 百度登陆协议分析!!!用libcurl来模拟百度登陆 C++使用libcurl做HttpClient 使用libcurl库进行HTTP的下载 li ...
随机推荐
- 决策树C4.5算法的技术深度剖析、实战解读
在本篇深入探讨的文章中,我们全面分析了C4.5决策树算法,包括其核心原理.实现流程.实战案例,以及与其他流行决策树算法(如ID3.CART和Random Forests)的比较.文章不仅涵盖了丰富的理 ...
- 每天5分钟复习OpenStack(十)Ceph 架构
在很多关于Ceph的文章中,通常会介绍一堆概念.虽然这些概念很重要,但是对于一个新手来说,同时接受太多的概念实际上很难消化.因此,在阅读本章节时要保持轻松的心情,只需要对所有的概念有个了解就可以了,因 ...
- 大数据分析/机器学习基础之matplotlib绘图篇
目录 一.前言 我的运行环境 二.什么是matplotlib? 三.安装及导入 四.matplotlib的使用 一.前言 本人因在学习基于python的机器学习相关教程时第一次接触到matplotli ...
- Snipaste安装与使用教程
一.下载 1.官网 下载地址 2.下载 可以直接在官网下载,也可以跳转微软仓库下载增强版的.如果是其他系统,mac在最下面,而Linux现在没有需要等待. 二.开始安装 1.下载完毕,是一压缩包绿色版 ...
- Java实现相似结构表算法
[产品需求] 对所有元数据进行分析,匹配出表字段相似度达到阈值的向相似结构表关系数据. 网上没有搜到相关算法实现,只能自己动手了. [算法实现] 简单点实现的话,可以轮询所有表,每张表都和其它表进行匹 ...
- Java并发(十七)----变量的线程安全分析
1.成员变量和静态变量是否线程安全 如果它们没有共享,则线程安全 如果它们被共享了,根据它们的状态是否能够改变,又分两种情况 如果只有读操作,则线程安全 如果有读写操作,则这段代码是临界区,需要考虑线 ...
- SpringBoot设置日志级别
输出到控制台 logging: # 日志记录到文件中 file: # 指定文件名 name: server.log logback: rollingpolicy: # 指定文件大小 max-file- ...
- ElasticSearch-Mapping类型映射-增删改查
https://www.elastic.co/guide/en/elasticsearch/reference/6.8/mapping.html 7.x版本后默认都是_doc类型 增加Mapping映 ...
- 【JVM】一文掌握JVM垃圾回收机制
作为Java程序员,除了业务逻辑以外,随着更深入的了解,都无法避免的会接触到JVM以及垃圾回收相关知识.JVM调优是一个听起来很可怕,实际上很简单的事. 感到可怕,是因为垃圾回收相关机制都在JVM的C ...
- 云MSP技本功|基于OGG 实现Oracle到Kafka增量数据实时同步
简介: 在大数据时代,存在大量基于数据的业务.数据需要在不同的系统之间流动.整合.通常,核心业务系统的数据存在OLTP数据库系统中,其它业务系统需要获取OLTP系统中的数据.传统的数仓通过批量数据同步 ...