C++开源库之Curl

关于Curl库

curl 是一个利用URL语法在命令行方式下工作的文件传输工具。它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。curl不但提供了一个可执行的工具库,还提供了供程序开发的libcurl库,该库使用c语言编写,支持跨平台,libcurl的下载地址点这里。下载的安装包里面有个Project文件夹,该目录下全是已经对用户提供的Visual
Studio工程库,包括Visual Studio的各个版本,提供代码示例以及库的编译,而且还提供多种编译方式,包括静态库,动态库,调试版、发布版,所谓真是业界良心的。提供的版本列表如下所示:

编译安装

编译curl库很简单的,找到自己对应的VS目录,然后打开工程,选择所需要的版本即可编译。我使用的是VS2010的静态库版本,因此选择VC10目录->LIB Debug版本,然后编译,编译后生成libcurld.lib和对应的调试信息文件libcurld.pdb,这样我们开发调试的时候只需要把该库文件和curl库的头文件文件夹curl加到我们的工程里面就可以使用curl库给我们提供的功能了。不过需要注意的是,因为CURL的特殊性,需要预定义一些宏和添加特定的依赖库,如下所示:

// 需要定义的宏,要不然会提示找不到某些函数的定义
#define BUILDING_LIBCURL
//#define HTTP_ONLY

// 依赖库
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "wldap32.lib")
#pragma comment(lib, "libcurld.lib")

主要函数列表

  • 全局初始化

    CURLcode curl_global_init(long flags);

    描述: 这个函数只能用一次(其实在调用curl_global_cleanup 函数后仍然可再用),如果这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动完成。

    参数:flags

    CURL_GLOBAL_ALL         //初始化所有的可能的调用。

    CURL_GLOBAL_SSL         //初始化支持 安全套接字层。

    CURL_GLOBAL_WIN32       //初始化win32套接字库。

    CURL_GLOBAL_NOTHING     //没有额外的初始化

  • 全局清理
    void curl_global_cleanup(void);

    描述:在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。

  • 获取Curl版本库
    char *curl_version();

    描述: 打印当前libcurl库的版本。

  • 初始化curl会话
    CURL *curl_easy_init();

    描述: curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样),相应的在调用结束时要用curl_easy_cleanup函数清理。一般curl_easy_init意味着一个会话的开始,它的返回值一般都用在easy系列的函数。

  • 清理cur会话
    void curl_easy_cleanup(CURL *handle);

    描述: 这个调用用来结束一个会话,与curl_easy_init配合着用。

    参数: CURL类型的指针。

  • 设置curl会话参数
    CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);

    描述: 这个函数最重要了,几乎所有的curl程序都要频繁的使用它,用来设置参数。它告诉curl库,程序将有如何的行为,比如要查看一个网页的html代码等。

    参数handle:CURL类型的指针

    参数option:各种CURLoption类型的选项。(都在curl.h库里有定义,man 也可以查看到)

    参数parameter: 这个参数既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量,它用什么这取决于第二个参数。

  • 执行curl会话
    CURLcode curl_easy_perform(CURL *handle);

    描述:这个函数在初始化CURL类型的指针以及curl_easy_setopt完成后调用,就像字面的意思所说perform就像是个舞台,让我们设置的option运作起来,执行curl所设置的动作。

    参数: CURL类型的指针

代码示例(参 C++使用libcurl做HttpClient

一个使用curl封装Post和Get方法的类

#ifndef __MY_CURL_H__
#define __MY_CURL_H__

#define BUILDING_LIBCURL
//#define HTTP_ONLY

#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 "my_curl.h"
#include "curl/curl.h"
#include <string>

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "wldap32.lib")
#pragma comment(lib, "libcurld.lib")

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_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;
}

从上述代码可以看出,使用curl库主要分为四个步骤:init,setopt,perform和cleanup,其中setopt最重要,用来指定参数

时间: 2024-08-10 23:10:47

C++开源库之Curl的相关文章

libCURL开源库在VS2010环境下编译安装,配置详解

libCURL开源库在VS2010环境下编译安装,配置详解 转自:http://my.oschina.net/u/1420791/blog/198247 CURL开源库VS2010环境下编译安装,配置详解 一 准备 1.1 CURL官网下载地址:http://curl.haxx.se/download.html 1.2 找到源码包,我这里下载的是7.32.0版:http://curl.haxx.se/download/curl-7.32.0.zip 二 步骤 2.1 打开curl-7.32.0\

各种有用的PHP开源库精心收集

转自:http://my.oschina.net/caroltc/blog/324024 摘要 各种有用的PHP开源库精心收集,包含图片处理,pdf生成,网络协议,网络请求,全文索引,高性能搜索,爬虫等等,项目肯定用得上的 PHP PHP开源库 目录[-] Swoole:重新定义PHP 1.html2ps and html2pdf    下载地址: http://www.tufat.com/script19.htm html2ps能够把带有图片,复杂表格(包含rowspan/colspan) ,

C/C++ 开源库及示例代码

C/C++ 开源库及示例代码 Table of Contents 说明 1 综合性的库 2 数据结构 & 算法 2.1 容器 2.1.1 标准容器 2.1.2 Lockfree 的容器 2.1.3 环形缓冲 2.1.4 多维数组 2.1.5 图 2.2 对容器的操作 2.3 字符串处理 2.3.1 字符集 2.3.2 字符串格式化 2.3.3 正则表达式 2.3.4 (其它) 2.4 内存相关 2.4.1 智能指针 2.4.2 内存池 2.5 时间 & 日期 2.6 编码 & 解码

Ubuntu虚拟机安装evpp开源库说明

Ubuntu虚拟机安装开源库说明: EVPP为奇虎360基于libevent开发的现代化的支持C++11特性的高性能网络库,自带TCP/UDP/HTTP等协议的异步非阻塞式的服务器和客户端库.拥有如下特性: * 现代版的C++11接口* 非阻塞异步接口都是C++11的functional/bind形式的回调仿函数(不是libevent中的C风格的函数指针)* 非阻塞纯异步多线程TCP服务器/客户端* 非阻塞纯异步多线程HTTP服务器/客户端* 非阻塞纯异步多线程UDP服务器* 支持多进程模式* 

linux下安装libcurl及开源库的一般安装步骤

前言 总有人说:要多看源代码!那么源代码去哪找呢?找到了又该怎么安装呢?本票博客不介绍如何使用和学习,只要讲获取和安装,以后会将curl和libevent的使用和学习. 一.开源库常用安装步骤 1.开源库下载 github全球最大的同性交流社区,还不赶紧get一下!里面有大量的开源项目和开源库,也可以上传自己的代码,注册一下帐户就可以了,这里就不讲怎么使用github了.注册可以去首页搜索:libevent,libevent是常规数据库安装,所以拿它来举例,如果懒得去搜,把地址直接给你:http

开源库BaseRecyclerViewAdapterHelper

相信大家RecyclerView应该不会陌生,大多数开发者应该都使用上它了,它也是google推荐替换ListView的控件,但是用过它的同学应该都知道它在某些方面并没有ListView使用起来方便,需要我们额外的编写代码,今天就给大家介绍一个开源库BaseRecyclerViewAdapterHelper,有了它让你使用RecyclerView的时候,和ListView一样的好用! 那么你要问了,BaseRecyclerViewAdapterHelper能做什么? 优化Adapter代码(减少

【计算机视觉】OpenCV的最近邻开源库FLANN

FLANN介绍 FLANN库全称是Fast Library for Approximate Nearest Neighbors,它是目前最完整的(近似)最近邻开源库.不但实现了一系列查找算法,还包含了一种自动选取最快算法的机制. flann::Index_类 该类模板是最近邻索引类,该类用于抽象不同类型的最近邻搜索的索引. 以下是flann::Index_类的声明: template <typename T> class #ifndef _MSC_VER FLANN_DEPRECATED #e

GitHub Top 100的Android开源库

本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择「Best Match」得到的结果,然后过滤了跟Android不相关的项目,所以排名并不具备任何官方效力,仅供参考学习,方便初学者快速了解当前一些流行的Android开源库. 1. React Native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native,

【开源框架】Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发,欢迎各位...

[转]http://www.tuicool.com/articles/jyA3MrU Android开源库 自己一直很喜欢Android开发,就如博客签名一样, 我是程序猿,我为自己代言 . 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者,而且我会 不定期的更新 这篇文章. Android下的优秀开发库数不胜数,在本文中,我列举的多是开发流程中最常用的一些.如果你还想了解更多的Android开源库,可以关注我的博客,每一个库都是我认真查看或者编译运行