使用libcurl作为Http client

产品通过HTTP协议为外部提供接口服务,常规情况是客户通过HTTP协议请求服务,服务结束后通过HTTP协议将服务记录POST到请求方。

用原生C实现了一个简单的HTTP Client,只有简单的功能:

1、实现HTTP GET/POST/PUT等方法;

2、POST支持参数和数据POST;

3、POST后接收返回值并关闭连接;

4、支持连接TIMEOUT、同步接收返回值TIMEOUT;

5、由于要设置超时,采用了多线程POST数据;

在业务量大了后,会频繁调用HTTP Client,且本身是多线程POST数据,出现了内存异常,问题一直没有找到。因此考虑了第三方开源组件,比如libevent(HTTP Server采用libevent实现的)、libcurl,最终选择了libcurl。

以下是结合网上例子修改的测试版本,测试后发现有内存泄漏问题,是由于自定义的http header指针未释放导致,并非网上所说curl_easy_perform导致。

#include <stdio.h>
#include <curl/curl.h>
#define PROC_SUCCESS 0
#define PROC_FAILED -1

static long gCount = 0;

int main()
{
time_t begin = time(NULL);
curl_global_init(CURL_GLOBAL_DEFAULT);
while(1)
{
const char *xml="<?xml />";
CurlPost("http://10.0.0.1:8090/xdr",xml);
gCount++;
if(gCount%10000==0)
{
time_t now = time(NULL);
fprintf(stdout,"CurlPost %ld usetime:%d
",gCount,now-begin);
begin = now;
}
usleep(10000);
}
curl_global_cleanup();
}

int CurlPost(const char *uri,const char *xml)
{
int iRet = PROC_SUCCESS;
CURL *curl = curl_easy_init();
if(curl==NULL)
{
fprintf(stderr,"curl_easy_init err:%ld
",gCount);
iRet = PROC_FAILED;
return iRet;
}
struct curl_slist *http_header = NULL;
http_header = curl_slist_append(http_header, "Accept: *");
http_header = curl_slist_append(http_header, "Content-Type: application/xml");
http_header = curl_slist_append(http_header, "Charset: utf-8");
http_header = curl_slist_append(http_header, "User-Agent: HYB-HTTPCLI");

curl_easy_setopt(curl,CURLOPT_URL,uri);
curl_easy_setopt(curl,CURLOPT_POSTFIELDS,xml);
curl_easy_setopt(curl,CURLOPT_POST,1);
curl_easy_setopt(curl,CURLOPT_HTTPHEADER, http_header);//设置HTTP HEADER
curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); //禁止产生信号(多线程时设置此选项)
curl_easy_setopt(curl,CURLOPT_TIMEOUT,1L); //超时1s
curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1); //完成后强制关闭连接
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr,"CurlPost err:%s
",curl_easy_strerror(res));
iRet = PROC_FAILED;
}
curl_slist_free_all(http_header);//http_header需要释放
curl_easy_cleanup(curl);
return iRet;
}

CURLOPT_POSTFIELDS选项的使用:

如果是POST参数,填写参数即可,libcurl会将参数自动放到请求行中,比如:

aa=12&bb=34

原文地址:https://www.cnblogs.com/cqvoip/p/8078989.html