HTTP/HTTPS客户端源码示例

HTTP/HTTPS客户端源码示例

环境:  zlib-1.2.8  openssl-1.0.1g  curl-7.36

Author:  Kagula

LastUpdateDate: 2014-04

阅读前提:CMake工具的基本使用、配置openssl-1.0.1g 开发环境

 

编译zlib库

         下载zlib-1.2.8.tar.gz并解压缩到" D:\SDK\zlib-1.2.8",使用CMake工具生成zlib.sln,在Visual Studio2013中打开并编译即可。

编译curl-7.36.0

    假设Open SSL已经安装到“D:\SDK\openssl-1.0.1g”,先设置下面的环境变量

OPENSSL_LIBRARIES=D:\SDK\openssl-1.0.1g\out32

OPENSSL_ROOT_DIR=D:\SDK\openssl-1.0.1g

    从http://curl.haxx.se/下载curl-7.36.0.zip并解压缩到“D:\SDK\curl-7.36.0”启动CMake工具Configure,分别设置LIB_EAY_RELEASESSL_EAY_RELEASE变量为“D:\SDK\openssl-1.0.1g\out32\libeay32.lib”,“D:\SDK\openssl-1.0.1g\out32\ssleay32.lib”,产生sln文件后打开,为里面的curl工程项目添加“USE_MANUAL”宏定义,然后build里面的4个项目成功。

   为项目添加链接库libcurl_imp.lib  , 把libcurl.dll文件复制到C++项目路径下,否则程序运行会提示找不到动态链接库。

下面是HTTP/HTTPS客户端示例

 Source.cpp如何调用的示例

#include <iostream>

using namespace std;

#include "HttpClient.h"

//下面是测试代码
using namespace kagula::network;

void TestHttpClient()
{
	CHttpClient client;
	string url;
	string post;
	string cookie="d:\\temp\\temp.txt";
	string response;

	url = "http://www.mydrivers.com";
	client.Get(url, response);
	cout << response << endl;;

	client.Post(url,post,cookie,response);
	cout << response << endl;

	url = "https://www.google.com.hk/";
	client.GetS(url, response, NULL);
	cout << response << endl;

	client.PostS(url, post, cookie, response, NULL);
	cout << response << endl;
}

int main(int argc, char *argv[])
{
	TestHttpClient();
	return 0;
}


HttpClient.h封装好的头文件

//HttpClient.h源代码清单
#ifndef _HTTPCLIENT_H_
#define _HTTPCLIENT_H_

#include <string>

/*
标题:从HTTP/HTTPS服务器中获取页面
测试环境:Windows 8.1
		Visual Studio 2013 SP1
		libcurl 7.36.0
说明:转自csdn某个页面,对源代码做了小修改,添加了Cookie的支持
参考资料:
《curl_eay_setopt手册》
http://www.helplib.net/s/linux.die/65_2740/man-3-curl-easy-setopt.shtml
《C++的cout高阶格式化操作》
http://www.cnblogs.com/devymex/archive/2010/09/06/1818754.html
*/

namespace kagula
{
	namespace network
	{
		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 strCookie 输入参数,Cookie文件名,例如 d:\temp\cookie.txt
			*                          如果为空,不启用Cookie.
			* @param strResponse 输出参数,返回的内容
			* @return 返回是否Post成功
			*/
			int Post(const std::string & strUrl, const std::string & strPost, 
				const std::string& strCookie, 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 strCookie 输入参数,Cookie文件名,例如 d:\temp\cookie.txt
			*                          如果为空,不启用Cookie.
			* @param strResponse 输出参数,返回的内容
			* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
			* @return 返回是否Post成功
			*/
			int PostS(const std::string & strUrl, const std::string & strPost, const std::string& strCookie, 
				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;

			bool PrintCookies(void* curl,std::string& strOut);
		};
	}
}
#endif


HttpClient.cpp

 

//HttpClient.cpp源代码清单
#include "HttpClient.h"
#include <iostream>
#include <curl/curl.h>
#include <iomanip>
#include <sstream>

namespace kagula
{
	namespace network
	{
		CHttpClient::CHttpClient(void) :
			m_bDebug(false)
		{

		}

		CHttpClient::~CHttpClient(void)
		{

		}

		bool CHttpClient::PrintCookies(void* curl, std::string& strOut)
		{
			std::ostringstream ostr;

			CURLcode res;
			struct curl_slist *cookies;

			res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
			if (res != CURLE_OK) {
				
				ostr << "Curl curl_easy_getinfo failed:" << curl_easy_strerror(res) << std::endl;
				strOut = ostr.str();
				return false;
			}
			const struct curl_slist *nc = cookies;
			int i = 1;
			ostr << "Cookies, curl knows:" << std::endl;
			while (nc) {
				ostr << "[" << i++ << "]: " << nc->data << std::endl;
				nc = nc->next;
			}

			return true;
		}

		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 = reinterpret_cast<std::string*>(lpVoid);
			if (NULL == str || NULL == buffer)
			{
				return -1;
			}

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

		int CHttpClient::Post(const std::string& strUrl, const std::string& strPost, const std::string& strCookie, 
			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);

			if (strCookie.length()>0)
			{ 
				curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)&strCookie);
				curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)&strCookie);
			}
				
			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, const std::string& strCookie, 
			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 (strCookie.length()>0)
			{
				curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)&strCookie);
				curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)&strCookie);
			}

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

补充阅读资料

使用libcurl实现上传文件到FTP服务器

http://blog.csdn.net/lee353086/article/details/5823145

 

使用libcurl下载http://www.baidu.com/img/baidu.gif示例

http://www.cppblog.com/qiujian5628/archive/2008/06/28/54873.html

 

libcurl的使用总结(一)

http://www.vimer.cn/2010/03/libcurl%E7%9A%84%E4%BD%BF%E7%94%A8%E6%80%BB%E7%BB%93%EF%BC%88%E4%B8%80%EF%BC%89.html

 

PHP的curl实现get,post 和 cookie

http://www.tsingpost.com/articles/201403/525.html

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。