天天看點

Curl 同步請求

同步請求相對較簡單,代碼示例如下:

//HttpClient.h  頭檔案

#ifndef __HTTP_CURL_H__
#define __HTTP_CURL_H__

#include <string>

class CHttpClient
{
public:
	static CHttpClient& GetInstance();

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

	/**
	* @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, const char* szHost = NULL);

	/**
	* @brief HTTP GET請求
	* @param strUrl 輸入參數,請求的Url位址,如:http://www.baidu.com
	* @param strResponse 輸出參數,傳回的内容
	* @return 傳回是否Post成功
	*/
    int Get(const std::string & strUrl, std::string & strResponse, const char* szHost = NULL);

	/**
	* @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* szHost = NULL, 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* szHost = NULL, const char * pCaPath = NULL);

	const char* GetErrorStr(const int& rknErrorCode);

};

#endif
           
//HttpClient.cpp 

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

#define TIME_OUT 10

CHttpClient& CHttpClient::GetInstance()
{
	static CHttpClient s_iHttpClient;
	return s_iHttpClient;
}

CHttpClient::CHttpClient(void)
{
	curl_global_init(CURL_GLOBAL_ALL);
}

CHttpClient::~CHttpClient(void)
{
	curl_global_cleanup();
}

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);
	}
	else if (NULL != pData)
	{
		printf("[UNKNOW]%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, const char* szHost)
{
	CURLcode res;
	CURL* curl = curl_easy_init();
	if(NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}
#define _DEBUG
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
#endif
	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, TIME_OUT);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, TIME_OUT);

	struct curl_slist *headers = NULL;
	if (NULL != szHost)
	{
		headers = curl_slist_append(headers, szHost);
		res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
	}
	res = curl_easy_perform(curl);
	if (NULL != szHost)
	{
		curl_slist_free_all(headers);
	}

	curl_easy_cleanup(curl);
	return res;
}

int CHttpClient::PostByHttpHead(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;
    }
#define _DEBUG
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
#endif
    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, TIME_OUT);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, TIME_OUT);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Get(const std::string & strUrl, std::string & strResponse, const char* szHost)
{
	CURLcode res;
	CURL* curl = curl_easy_init();
	if(NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}
#define _DEBUG
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
#endif
	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, TIME_OUT);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, TIME_OUT);
    struct curl_slist *headers = NULL;
    if (NULL != szHost)
    {
        headers = curl_slist_append(headers, szHost);
        res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    }
	res = curl_easy_perform(curl);
    if (NULL != szHost)
    {
        curl_slist_free_all(headers);
    }
	curl_easy_cleanup(curl);
	return res;
}

int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char* szHost, const char * pCaPath)
{
	CURLcode res;
	CURL* curl = curl_easy_init();
	if(NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}
#define _DEBUG
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
#endif
	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, TIME_OUT);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, TIME_OUT);

	struct curl_slist *headers = NULL;
	if (NULL != szHost)
	{
		headers = curl_slist_append(headers, szHost);
		res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
	}
	res = curl_easy_perform(curl);
	if (NULL != szHost)
	{
		curl_slist_free_all(headers);
	}

	curl_easy_cleanup(curl);
	return res;
}

int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char* szHost, const char * pCaPath)
{
	CURLcode res;
	CURL* curl = curl_easy_init();
	if(NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}
#define _DEBUG
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
#endif
	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, TIME_OUT);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, TIME_OUT);

	struct curl_slist *headers = NULL;
	if (NULL != szHost)
	{
		headers = curl_slist_append(headers, szHost);
		res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
	}
	res = curl_easy_perform(curl);
	if (NULL != szHost)
	{
		curl_slist_free_all(headers);
	}

	curl_easy_cleanup(curl);
	return res;
}

const char* CHttpClient::GetErrorStr(const int& rknErrorCode)
{
	return curl_easy_strerror(CURLcode(rknErrorCode));
}
           

調用示例:

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
#include "HttpClient.h"

int main()
{
    std::string  strResponse;
    CHttpClient::GetInstance()->Get("www.baidu.com",strResponse);
    printf("strResponse = %s\n", strResponse.c_str());
    return 0;
}
           

繼續閱讀