libcurl被很多软件厂商使用,libcurl提供了使用C或C++语言支持http访问,所有常用于客户端软件
本例学习了libcurl的写法,上代码:
#pragma once
#ifndef __RESTCLIENTPOOL_H__
#define __RESTCLIENTPOOL_H__
#include "./libcurl-vc16-x86-release-dll-ipv6-sspi-schannel/include/curl/curl.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <string>
#include <vector>
#include <queue>
using namespace std;
typedef size_t(*callback_func)(void* ptr, size_t size, size_t nmemb, void* stream);
struct curl_data
{
string* response;
callback_func cb;
curl_data(const char* pUrl, callback_func func)
{
response = new std::string(pUrl);
cb = func;
}
~curl_data()
{
delete response;
}
};
class RestClientPool
{
public:
RestClientPool(void);
~RestClientPool(void);
public:
/**
* @brief HTTP GET请求
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strResponse 输出参数,返回的内容
* @return 返回是否Post成功
*/
int Get(callback_func cb, std::string * strResponse);
public:
void SetDebug(bool bDebug);
int GlobleInit();//全局初始化,主程序调用一次
void GlobleFint();
CURL* GetCurl();
CURL* CreateCurl();
void PutCurl(CURL* curl);
private:
bool m_bDebug;
queue<CURL* > m_VectCurl;
vector< curl_slist*> m_VectSlist;
HANDLE hMutex;
};
#endif
// curl_multi_test.cpp : 定义控制台应用程序的入口点。
//
#include "RestClientPool.h"
// 唯一的应用程序
# pragma comment(lib, "libcurl-vc16-x86-release-dll-ipv6-sspi-schannel/lib/libcurl.lib")
RestClientPool::RestClientPool(void) :
m_bDebug(false)
{
GlobleInit();//全局初始化,主程序调用一次
hMutex = CreateMutex(NULL, FALSE, NULL);
}
RestClientPool::~RestClientPool(void)
{
for (curl_slist* p : m_VectSlist) {
if (p != nullptr)
curl_slist_free_all(p);
}
m_VectSlist.clear();
if (m_VectCurl.size() > 0)
{
CURL* curl = m_VectCurl.front();
m_VectCurl.pop();
while (curl != nullptr) {
curl_easy_cleanup(curl);
if (m_VectCurl.size() <= 0)
break;
curl = m_VectCurl.front();
m_VectCurl.pop();
}
}
CloseHandle(hMutex);
GlobleFint();
}
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;
}
CURL* RestClientPool::GetCurl()
{
CURL* curl = NULL;
WaitForSingleObject(hMutex, INFINITE);
if (m_VectCurl.size() > 0)
{
curl = m_VectCurl.front();
m_VectCurl.pop();
}
ReleaseMutex(hMutex);
if (curl == NULL)
{
curl = CreateCurl();
}
return curl;
}
void RestClientPool::PutCurl(CURL* curl)
{
WaitForSingleObject(hMutex, INFINITE);
m_VectCurl.push(curl);
ReleaseMutex(hMutex);
}
CURL* RestClientPool::CreateCurl()
{
CURL* curl = curl_easy_init();
if (NULL == curl)
{
return NULL;
}
curl_slist* list = nullptr;
list = curl_slist_append(list, "Accept: text/json");
//list = curl_slist_append(list, "Accept-Encoding: gzip");
list = curl_slist_append(list, "Accept-Language: zh-CN,zh;q=0.9");
list = curl_slist_append(list, "Content-Type: text/json");
list = curl_slist_append(list, "Host: localhost:80");
list = curl_slist_append(list, "Connection: Keep-Alive");
//list = curl_slist_append(list, "Cookie: em_hq_fls=js; qgqp_b_id=7473a399162f1995601a1fb59c4bd05f; ct=2ix0h5AQ4v538wkocKxPcY_ilboT2srS08hrjybizJ5Kc58v02kimh6AZe2Yz7Z4p_1KLU7-LIqeBaC2WyrERVzjx1K9g8RgMIs1vO-lBw9ao0KHJ_bvxJhQkdtJspPVs3fqpWLR-rGfdSEiB6055Aqg2ux3Ej_WVoLrW9EXhrU");
list = curl_slist_append(list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
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);
/* enable TCP keep-alive for this transfer */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
/* keep-alive idle time to 120 seconds */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 300L);
/* interval time between keep-alive probes: 60 seconds */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 20L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
/**
* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
*/
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 20);
m_VectSlist.push_back(list);
return curl;
}
void RestClientPool::SetDebug(bool bDebug)
{
m_bDebug = bDebug;
}
int RestClientPool::GlobleInit()//全局初始化,主程序调用一次
{
return curl_global_init(CURL_GLOBAL_ALL);
}
void RestClientPool::GlobleFint()
{
curl_global_cleanup();
}
int RestClientPool::Get(callback_func func, std::string* strResponse)
{
int res;
//CURL* curl = CurlMutiTreadMutex::GetInstance()->muti_curl_easy_init();
CURL* curl = GetCurl();
if (NULL == curl)
{
return CURLE_FAILED_INIT;
}
curl_easy_setopt(curl, CURLOPT_URL, strResponse->c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, func);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)strResponse);
res = curl_easy_perform(curl);
if (res != 0)
{
printf("curl_easy_perform error %d\n", res);
}
PutCurl(curl);
return res;
}
bool ctrlhandler(DWORD fdwctrltype)
{
bool bRet = false;
switch (fdwctrltype)
{
// handle the ctrl-c signal.
case CTRL_C_EVENT:
printf("ctrl-c event\n\n");
bRet = true;
break;
// ctrl-close: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
printf("ctrl-close event\n\n");
bRet = true;
break;
// pass other signals to the next handler.
case CTRL_BREAK_EVENT:
printf("ctrl-break event\n\n");
bRet = false;
break;
case CTRL_LOGOFF_EVENT:
printf("ctrl-logoff event\n\n");
bRet = false;
break;
case CTRL_SHUTDOWN_EVENT:
printf("ctrl-shutdown event\n\n");
bRet = false;
break;
default:
break;;
}
return bRet;
}
还有多线程并发的例子,欢迎到我的资源下载学习,彻底掌握libcurl