libCurl是一个多协议、跨平台的客户端URL传输库;使用libCurl可方便地进行HTTP请求。
接口说明
libCurl提供easy interface
和multi interface
两种HTTP请求方式;本文主要是easy interface
的使用说明。
使用步骤
libCurl主要采用Callback方式完成数据传输,设置好参数后和回调函数后,在满足条件时会自动调用相应的回调函数实现对应功能。一般按如下顺序调用:
CURLcode curl_global_init(long flags)
:初始化库(只能调用一次),若在调用curl_easy_init
时还未调用此函数,则libCurl库会自动调用此初始化函数。CURL *curl_easy_init()
:初始化一个CURL指针(easy_handle对象,用于一系列easy函数中)。CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter)
:设置传输选项(参数及回调函数);一般会多次调用。CURLcode curl_easy_perform(CURL *handle)
:完成传输任务。void curl_easy_cleanup(CURL *handle)
:清理释放void curl_global_cleanup(void)
:清理库,在使用结束时调用。
setopt函数部分选项说明
curl所有设置都是在curl_easy_setopt中完成,其选项众多;部分常见选项:
CURLOPT_URL
:设定请求的URL;CURLOPT_HTTPHEADER
:设定请求的HTTP头数据;CURLOPT_POSTFIELDS,CURLOPT_POSTFIELDSIZE
:POST请求时,设定发送的数据和长度。CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
:设定如何处理接收到的数据,WRITEFUNCTION设定回调函数size_t callback(void *ptr, size_t size, size_t nmemb, void *stream)
,其中stream参数即为通过WRITEDATA设定的参数。CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
:设定如何处理接收到的HTTP头数据;CURLOPT_VERBOSE
:设定输出信息,当第三个参数为1时,会输出详细的操作信息(方便调试);CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOU
:设定传输与请求的超时时间,单位为秒;CURLOPT_FOLLOWLOCATION,CURLOPT_MAXREDIRS
:设定是否允许重定向(FOLLOWLOCATION非零时,会自动处理302错误),及最大重定向次数;
示例
以下是get与post请求的示例程序。
写数据回调
在有数据接收到时会被调用,size*nmemb是接收到的数据长度,userp是用户传递的接收数据的指针(示例中为string指针)。
static size_t http_curl_write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
if(NULL==userp || NULL==buffer || 0 == size)
return 0;
size_t realSize = size*nmemb;
std::string *pstr = (std::string*)userp;
if(NULL != pstr){
pstr->append((const char*)buffer, realSize);
}
return realSize;
}
GET请求
请求的头信息通过map传入,返回接收到的response。
- 请求头通过curl_slist_append组成一个链表后,作为参数传入;
- CURLOPT_POST设为零;表示为GET请求;
- 在perform请求成功后,还需通过curl_easy_getinfo获取对应的返回code,以判断请求是否真正成功。
string getRequest(const string &strUrl, const std::map<string, string> &mapHeader) {
CURL *curl = curl_easy_init();
if(NULL == curl){
// ERROR:
return "ERROR: call curl_easy_init fail";
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
for(auto &h:mapHeader){
headers = curl_slist_append(headers, buildHeader(h).c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POST, 0); // GET request
string strResp;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&strResp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_curl_write_data);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
CURLcode res = curl_easy_perform(curl);
bool bRet = false;
if(res != CURLE_OK){ // connect fail
// ERROR
strResp = "ERROR: Connect fail: " + res;
}
else{
long respCode;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respCode);
if(respCode == 200) {
bRet = true; // success
}
else{
// error-info in strResp
}
}
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
return strResp;
}
POST请求
发送的数据以JSON字符串参数的形式传入:
- 默认即为POST请求,不需要做特殊设定;
- 通过POSTFIELDS与POSTFIELDSIZE设定要发送的JSON数据;
string postRequest(string strUrl, string strJson) {
CURL *curl = curl_easy_init();
if(NULL == curl){
// ERROR:
return "ERROR: call curl_easy_init fail";
}
curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strJson.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strJson.length());
string strResp;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&strResp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_curl_write_data);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
CURLcode res = curl_easy_perform(curl);
bool bRet = false;
if(res != CURLE_OK){ // connect fail
// ERROR
strResp = "ERROR: Connect fail";
}
else{
long respCode;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respCode);
if(respCode == 200) {
bRet = true; // success
}
else{
// error-info in strResp
}
}
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
return strResp;
}