用libCURL库post json数据

libcurl是优秀的C语言版http 库,时间比较久,目前支持也比较完善,官方网页见 https://curl.haxx.se/libcurl/ 

对很多协议都有很好的支持。

别的语言都有对http较完善的库支持, 在C/C++领域Libcurl可能是最好用的了吧。我本来是打算用Qt里面的Qnetworkmanager,无奈实在是太难用,这一点qt做的实在不怎么的。


 

一、编译

只说Windows下编译(32位)
官方下载源码,找到winbuild目录。打开vs2013开发人员命令提示工具,编译debug版本:

nmake /f Makefile.vc mode=static VC=12 DEBUG=yes 

编译relase版本设置DEBUG=no就可以了; 生成两个文件:

在builds目录下找到生成的include和lib目录用来进行程序开发;在Windows下,debug版与release版不能通用。

libcurl_a_debug.lib

libcurl_a.lib

二、工程设置

分别将include目录和lib引入工程,windows平台下qt 的.pro文件是这样写的:

curl头文件放在include/curl目录下。debug和release用的curl的库不是同一个,否则会在运行时出错。

INCLUDEPATH += \
	$$PWD/include \

win32{
	Release:LIBS +=-L$$PWD/lib  -llibcurl_a
	Debug:LIBS+=-L$$PWD/lib -llibcurl_a_debug
}

三、写代码 

1.引入头文件

用静态链接方式的话,必须定义这个宏。

#define CURL_STATICLIB   //静态链接
#include <curl/curl.h>

2.主要流程

curl_easy_init();进行初始化操作

 curl_easy_setopt(curl,  A, Value);  这个函数用于设置http各个参数

CURLOPT_DEBUGFUNCTION 指定调试输出时调用的函数。这里是OnDebug。具体可以参照 https://blog.csdn.net/mao834099514/article/details/54947853 中的例子。

    CURLcode res;  
    CURL* curl = curl_easy_init();  
	if (NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}

	if ( false )//用于调试的设置
	{
		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_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_MS, 3000);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300);

	
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);  //支持服务器跳转
	curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);  // enable TCP keep-alive for this transfer 
	curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);	// keep-alive idle time to 120 seconds 
	curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);	// interval time between keep-alive probes: 60 seconds

	struct curl_slist* headers = NULL;
	headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
	curl_easy_setopt(curl, CURLOPT_POST, 1);//设置为非0表示本次操作为POST

	res = curl_easy_perform(curl);
	//curl_easy_cleanup(curl);
	return res;

3.注意要点

一是上传json需要 在http头中加入"Content-Type:application/json;charset=UTF-8"

可以用curl_easy_setopt()函数实现。

二是如果需要保持长连接,需要CURLOPT_TIMEOUT 的设置一定要大于CURLOPT_TCP_KEEPIDLE的设置,或者设置为默认值0(不超时), 否则可能你还没等到应答就已经超时了。

参考:https://blog.csdn.net/sgiwxyg/article/details/45875081

三是 curl_easy_cleanup(curl); 会释放资源,如果释放后再curl_easy_init();发送数据会重新进行连接,

因此不要执行    curl_easy_cleanup(curl);  下一次发送数据时,才可以重用连接。

四是用好OnDebug函数,可以调试http发送过程。

OnDebug函数和OnWriteData函数如下:

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;  
}  
  
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;  
}  

 

 

 

 

参考:https://blog.csdn.net/mao834099514/article/details/54947853  调试代码是从这拿过来的。

 

上一篇:【php】curl


下一篇:curl模拟多线程