#include <curl/curl.h>
#include <string>
using std::string;
class HttpClient
{
public:
static size_t WriteData(char *data, size_t block_size, size_t block_count, string *response)
{
if(data == NULL) return 0;
size_t len = block_size * block_count;
response->append(data, len);
return len;
}
static size_t WriteFile(char *data, size_t block_size, size_t block_count, FILE *file)
{
if(data == NULL) return 0;
size_t len = block_size * block_count;
fwrite(data, len, 1, file);
return len;
}
HttpClient():m_pcurl(NULL)
{
m_pcurl = curl_easy_init();
}
~HttpClient()
{
curl_easy_cleanup(m_pcurl);
}
string Error() {return m_error;}
string Header() {return m_header;}
string Response() {return m_response;}
long HttpCode(){return m_response_code;}
bool Get(const string &url, int timeout)
{
return Request(url, "", "get", timeout);
}
bool Put(const string &url, const string &request, int timeout)
{
return Request(url, request, "put", timeout);
}
bool Post(const string &url, const string &request, int timeout)
{
return Request(url, request, "post", timeout);
}
bool Delete(const string &url, int timeout)
{
return Request(url, "", "delete",timeout);
}
bool Save( const std::string &url, const char *filename, int timeout)
{
m_error = "";
m_response_code = 0;
FILE* file = fopen(filename, "wb");
curl_easy_reset(m_pcurl);
curl_easy_setopt(m_pcurl, CURLOPT_URL, url.c_str());
curl_easy_setopt(m_pcurl, CURLOPT_WRITEFUNCTION, WriteFile);
curl_easy_setopt(m_pcurl, CURLOPT_WRITEDATA, file);
curl_easy_setopt(m_pcurl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_pcurl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(m_pcurl, CURLOPT_TIMEOUT, timeout);
CURLcode rc = curl_easy_perform(m_pcurl);
fclose(file);
if(rc != CURLE_OK)
{
m_error = string(curl_easy_strerror(rc));
return false;
}
rc = curl_easy_getinfo(m_pcurl, CURLINFO_RESPONSE_CODE , &m_response_code);
if(rc != CURLE_OK)
{
m_error = string(curl_easy_strerror(rc));
return false;
}
return true;
}
private:
bool Request(const string &url, const string &request, string method, int timeout)
{
m_error = "";
m_response_code = 0;
m_response.clear();
m_header.clear();
curl_easy_reset(m_pcurl);
curl_easy_setopt(m_pcurl, CURLOPT_URL, url.c_str());
curl_easy_setopt(m_pcurl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(m_pcurl, CURLOPT_TIMEOUT, timeout);
curl_easy_setopt(m_pcurl, CURLOPT_WRITEFUNCTION, WriteData);
curl_easy_setopt(m_pcurl, CURLOPT_WRITEDATA, &m_response);
curl_easy_setopt(m_pcurl, CURLOPT_HEADERFUNCTION, WriteData);
curl_easy_setopt(m_pcurl, CURLOPT_WRITEHEADER, &m_header);
if(method == "get")
{
curl_easy_setopt(m_pcurl, CURLOPT_HTTPGET, 1);
}
else if(method == "post")
{
curl_easy_setopt(m_pcurl, CURLOPT_POST, 1L);
curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDSIZE, request.length());
curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDS, request.c_str());
}
else if(method == "put")
{
curl_easy_setopt(m_pcurl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDSIZE, request.length());
curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDS, request.c_str());
}
else if(method == "delete")
{
curl_easy_setopt(m_pcurl, CURLOPT_CUSTOMREQUEST, "DELETE");
}
else
{
m_error = "method not support: " + method;
return false;
}
CURLcode rc = curl_easy_perform(m_pcurl);
if(rc != CURLE_OK)
{
m_error = string(curl_easy_strerror(rc));
return false;
}
rc = curl_easy_getinfo(m_pcurl, CURLINFO_RESPONSE_CODE , &m_response_code);
if(rc != CURLE_OK)
{
m_error = string(curl_easy_strerror(rc));
return false;
}
return true;
}
private:
CURL *m_pcurl;
string m_error;
string m_header;
string m_response;
long m_response_code;
};
以上是使用curl封装的HttpClient;工作中使用过的,默认支持长连接。
遇到过的curl缺陷与陷阱
1、对url中的空格是不进行编码的
解决方法:使用时需要对空格进行替换为:”%20”.
2、跟服务器交互时,如果跟服务失去连接会导致僵尸(阻塞在poll)
解决方式:可以设置一个超时时间