动易网站地图,免备案域名解析,网站在哪备案,东莞网站设计开发CURL开源库介绍
CURL 是一个功能强大的开源库#xff0c;用于在各种平台上进行网络数据传输。它支持众多的网络协议#xff0c;像 HTTP、HTTPS、FTP、SMTP 等#xff0c;能让开发者方便地在程序里实现与远程服务器的通信。 CURL 可以在 Windows、Linux、macOS 等多种操作系…CURL开源库介绍
CURL 是一个功能强大的开源库用于在各种平台上进行网络数据传输。它支持众多的网络协议像 HTTP、HTTPS、FTP、SMTP 等能让开发者方便地在程序里实现与远程服务器的通信。 CURL 可以在 Windows、Linux、macOS 等多种操作系统上使用 CURL 支持多种网络协议能处理复杂的网络请求如设置请求头、处理 cookies、上传和下载文件等。 使用前编译CURL 源码生成动态库引入时包括头文件一起网上也有别人已经编译好的现成的库可以下载使用。 生成的库 在你要使用的项目里加上curl的头文件
#include curl\curl.h这下你就可以使用CURL里的接口完成功能了。
CURL常用的接口说明
初始化与清理相关的接口
curl_easy_init() 功能创建并初始化一个新的 CURL 句柄用于后续的网络操作。这个句柄就像一个会话的载体后续的请求设置和执行都围绕它展开。 返回值成功时返回一个指向新创建的 CURL 句柄的指针失败则返回 NULL。curl_easy_cleanup(CURL *handle) 功能释放 CURL 句柄占用的所有资源包括内存、网络连接等。在使用完 CURL 句柄后必须调用此函数以避免资源泄漏。 参数handle 是之前通过 curl_easy_init() 得到的 CURL 句柄。
请求选项设置相关的接口
curl_easy_setopt(CURL *handle, CURLoption option, …) 功能设置 CURL 句柄的各种选项这些选项可以控制请求的各个方面如请求的 URL、请求方法、请求头、回调函数等。 参数 handleCURL 句柄。 optionCURLoption 类型的常量指定要设置的选项。 可变参数根据不同的 option需要传入相应的参数值。 常用 option 有 CURLOPT_URL设置请求的 URL。 CURLOPT_POST将请求方法设置为 POST。 CURLOPT_HTTPHEADER设置请求头。 CURLOPT_POSTFIELDS设置 POST 请求的数据。curl_slist_append(struct curl_slist *list, const char *string) 功能用于构建一个链表来存储请求头信息。每次调用该函数可以将一个新的请求头字符串添加到链表中。 参数 list指向 curl_slist 链表的指针如果是第一次添加可传入 NULL。 string要添加的请求头字符串格式为 Header-Name: Header-Value。 返回值返回更新后的链表指针。
回调函数设置相关的接口
CURLOPT_WRITEFUNCTION 和 CURLOPT_WRITEDATA 功能CURLOPT_WRITEFUNCTION设置一个回调函数当服务器返回响应数据时CURL 会调用该回调函数来处理响应数据。 CURLOPT_WRITEDATA传递一个用户自定义的指针给回调函数用于在回调函数中存储或处理数据。CURLOPT_READFUNCTION 和 CURLOPT_READDATA 功能CURLOPT_READFUNCTION设置一个回调函数用于在发送数据时从用户提供的数据源中读取数据。 CURLOPT_READDATA传递一个用户自定义的指针给回调函数用于标识数据源。
多线程与异步操作相关的接口
curl_multi_init() 功能初始化一个 CURLM 句柄用于多线程或异步的网络操作。该句柄可以管理多个 CURL 句柄实现并发请求。 返回值成功时返回一个新的 CURLM 句柄指针失败返回 NULL。curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle) 功能将一个 CURL 句柄添加到 CURLM 句柄管理的句柄列表中以便进行并发处理。 参数 multi_handleCURLM 句柄。 easy_handle要添加的 CURL 句柄。curl_multi_perform(CURLM *multi_handle, int *still_running) 功能在 CURLM 句柄管理的所有 CURL 句柄上执行网络操作。该函数会尝试处理尽可能多的请求并返回仍在运行的请求数量。 参数 multi_handleCURLM 句柄。 still_running指向一个整数的指针用于存储仍在运行的请求数量。curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle) 功能从 CURLM 句柄管理的句柄列表中移除一个 CURL 句柄。 参数 multi_handleCURLM 句柄。 easy_handle要移除的 CURL 句柄。curl_multi_cleanup(CURLM *multi_handle) 功能释放 CURLM 句柄占用的所有资源。在使用完 CURLM 句柄后必须调用此函数进行清理。 参数multi_handle 是 CURLM 句柄。
接口流程使用
简单的同步调用模式的使用流程
调用curl_global_init()初始化libcurl 调用curl_easy_init()函数得到 easyinterface型指针 调用curl_easy_setopt()设置传输选项根据curl_easy_setopt()设置的传输选项实现回调函数以完成用户特定任务调用curl_easy_perform()函数完成传输任务,返回错误码 调用curl_easy_cleanup()释放内存调用curl_global_cleanup() (可以不用调用)
在整过过程中设置curl_easy_setopt()参数是最关键的,了解相关参数及对应作用很重要。
举例说明CURL的调用实现
//http回调写函数
static size_t CurlWriteBuffer(char *buffer, size_t size, size_t nmemb, std::string* stream)
{//第二个参数为每个数据的大小第三个为数据个数最后一个为接收变量size_t sizes size*nmemb;if(stream NULL) return 0;stream-append(buffer,sizes);return sizes;
}//http发送封装
int HttpClient::posturl(std::string msg, std::string url, bool IsSSL)
{CURL* pCurlNULL; //一个libcurl的handleCURLcode res; //返回状态码std::string response; //返回信息curl_global_init(CURL_GLOBAL_ALL); //全局初始化pCurl curl_easy_init(); //创建一个handle//设置请求头struct curl_slist* pHeader NULL;//传json格式字符编码为utf8header_ curl_slist_append(pHeader ,Content-Type: application/json;charsetutf-8);//添加请求头到handlecurl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pHeader );//设置URLcurl_easy_setopt(pCurl, CURLOPT_URL, url.c_str()); CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理curl_easy_setopt(pCurl,CURLOPT_POSTFIELDS,msg.c_str()); //post请求消息数据 curl_easy_setopt(pCurl,CURLOPT_POSTFIELDSIZE,msg.length()); //消息长度curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, CurlWriteBuffer); //回调函数curl_easy_setopt(pCurl,CURLOPT_WRITEDATA,response); //数据接收变量curl_easy_setopt(pCurl,CURLOPT_TIMEOUT,m_settinginfo.m_http_timeout); //连接超时时间//不支持ssl验证if(m_settinginfo.m_ssl 0){curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0);//设定为不验证证书和HOSTcurl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0);}else{// 配置 https 请求所需证书if (m_settinginfo.m_ssl 1) //ssl单向验证不验证服务器{curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L); }else{//双向验证curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0);curl_easy_setopt(pCurl,CURLOPT_CAINFO,ca_info.ca_path.c_str()); }//设置客户端信息curl_easy_setopt(pCurl, CURLOPT_SSLCERT, ca_info.client_cert_path.c_str());curl_easy_setopt(pCurl,CURLOPT_SSLCERTTYPE,PEM); curl_easy_setopt(pCurl, CURLOPT_SSLKEY, ca_info.client_key_path.c_str());curl_easy_setopt(pCurl,CURLOPT_SSLKEYTYPE,PEM); //如果客户端证书密钥使用密码加密设置加密密码//curl_easy_setopt(pCurl, CURLOPT_KEYPASSWD, your_key_password);}//执行http连接res curl_easy_perform(pCurl);//清除消息头curl_slist_free_all(pHeader);//清除handlecurl_easy_cleanup(pCurl);return 0;
}再看一段完整的CURL封装成getpost等形式进行字串传输和文件上传的请求可以直接拿去使用。
//Http的Get请求
int HttpClient::ExecuteGetRequestCURL(const char* strUrl, const char* pszGet, const char* pszCookie, int nTimeOut)
{CURLcode res;m_strResponse ;struct curl_slist* headers NULL;CURL* curl curl_easy_init();if (NULL curl){return CURLE_FAILED_INIT;}std::string strOutData strUrl;strOutData pszGet;curl_easy_setopt(curl, CURLOPT_URL, strOutData.c_str());curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)m_strResponse);/*** 当多个线程都使用超时处理的时候同时主线程中有sleep或是wait等操作。* 如果不设置这个选项libcurl将会发信号打断这个wait从而导致程序退出。*/curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);//连接超时设置10s,数据请求超时设置60scurl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeOut);res curl_easy_perform(curl);if (res ! CURLE_OK)m_strResponse ;curl_easy_cleanup(curl);return res;
}
//Http的post请求
int HttpClient::ExecutePostRequestCURL(const char* strUrl, const char* pszKey, const char* pszPost, const char* pszCookie, int nTimeOut)
{CURLcode res;m_strResponse ;CURL* curl curl_easy_init();if (NULL curl){return CURLE_FAILED_INIT;}///struct curl_slist* headerlist NULL;struct curl_httppost* formpost NULL;struct curl_httppost* last NULL;//headerlist curl_slist_append(headerlist, Content-Type:application/json;charsetUTF-8);//curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);res curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, gzip, deflate, br);//设置CURLOPT_ACCEPT_ENCODING 7.21.8之前为CURLOPT_ENCODING if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}curl_formadd(formpost, last, CURLFORM_PTRNAME, pszKey, CURLFORM_PTRCONTENTS, pszPost, CURLFORM_END); //以这种方式上传可以避免特殊字符被改变if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); //构造post参数 if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}/curl_easy_setopt(curl, CURLOPT_URL, strUrl);if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}//curl_easy_setopt(curl, CURLOPT_POST, 1);//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pszPost);curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)m_strResponse);if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);if (CURLE_OK ! res){curl_easy_cleanup(curl);return CURLE_FAILED_INIT;}if ((pszCookie ! NULL)(strlen(pszCookie)0)){ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pszCookie);curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pszCookie);}//连接超时设置,数据请求超时设置curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeOut);res curl_easy_perform(curl);if (res ! CURLE_OK){m_strResponse ;// 获取详细错误信息const char* szErr curl_easy_strerror(res);fprintf(stderr, curl_easy_perform() failed: %s\n, szErr);}// 清空curl_easy_cleanup(curl);// 释放表单curl_formfree(formpost);// 释放表头curl_slist_free_all (headerlist); return res;
}//https的Get请求
int HttpClient::ExecuteHttpsGetCURL(const std::string strUrl, const char* pszGet, const char * pCaPath, int nTimeOut)
{CURLcode res;CURL* curl curl_easy_init();if (NULL curl){return CURLE_FAILED_INIT;}std::string strOutData strUrl;strOutData pszGet;curl_easy_setopt(curl, CURLOPT_URL, strOutData.c_str());curl_easy_setopt(curl, CURLOPT_HEADER, 0 ); curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)m_strResponse);curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeOut);if (NULL pCaPath){curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);}else{curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);}curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);//curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);//curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);//curl_easy_setopt(curl,CURLOPT_TRANSFERTEXT,1); res curl_easy_perform(curl);if (res ! CURLE_OK)m_strResponse ;curl_easy_cleanup(curl);return res;
}//https的Post请求
int HttpClient::ExecuteHttpsPostCURL(const std::string strUrl, const std::string strKey, const std::string strPost, const std::string strCookie, const char* pCaPath, int nTimeOut)
{CURLcode res;CURL* curl curl_easy_init();if (NULL curl){return CURLE_FAILED_INIT;}///struct curl_slist* headers NULL;struct curl_httppost* post NULL;struct curl_httppost* last NULL;curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, gzip, deflate, br);//设置CURLOPT_ACCEPT_ENCODING 7.21.8之前为CURLOPT_ENCODING curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);curl_formadd(post, last, CURLFORM_PTRNAME, strKey.c_str(), CURLFORM_PTRCONTENTS, strPost.c_str(), CURLFORM_END); //以这种方式上传可以避免特殊字符被改变curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); //构造post参数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 *)m_strResponse);curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);//curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60*5);//curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60*5);if (strCookie.length()0){curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)strCookie);curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)strCookie);}if (NULL pCaPath){//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);}else{//缺省情况就是PEM所以无需设置另外支持DER//curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,PEM);curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);}curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 20);curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeOut);curl_easy_setopt(curl, CURLOPT_SSLVERSION, 3);res curl_easy_perform(curl);curl_easy_cleanup(curl);return res;
}static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{ std::string* str reinterpret_caststd::string*(lpVoid);if (NULL str || NULL buffer){return -1;}char* pData reinterpret_castchar*(buffer);str-append(pData, size * nmemb);return nmemb;
}long HttpClient::GetRespone(char* pszResponse, long lRespLen)
{long lRet 0;if (m_strResponse.length() 0){lRet 1;goto err;}if (pszResponse NULL){lRespLen m_strResponse.length();goto err;}if (lRespLen m_strResponse.length()){lRet 1;goto err;}memset(pszResponse, 0, lRespLen);memcpy(pszResponse, m_strResponse.c_str(), m_strResponse.length());lRespLen m_strResponse.length();
err:return lRet;
}long HttpClient::GetFileNameAndExt(const std::string strFilePath,std::string strFileName,std::string strFileExt)
{long lRet 0;strFileExt ;strFileName ;int nPos strFilePath.rfind(.);if (nPos -1){lRet CURLE_FAILED_INIT; //文件不存在goto err;}strFileExt strFilePath.substr(nPos1, strFilePath.length());nPos strFilePath.rfind(\\);if (nPos -1){nPos strFilePath.rfind(/);if (nPos -1){strFileName strFilePath;goto err;}}strFileName strFilePath.substr(nPos1, strFilePath.length());
err:return lRet;
}
//Http的post传文件请求
//strParamName是bindingSeal,strParamVal值是对应的json包,strParamName2是sealImages,strParamVal2值是图片名称
long HttpClient::HttpUploadFileCURL(LPCTSTR strUrl, const string strFilePath, const string strParamName, const string strParamVal, const string strParamName2, const string strParamVal2, string strResponse)
{CURL* curl;CURLcode res;long lRet 0;std::string strFileName;std::string strFileExt;StringTool strTool;string strCRUL strTool.WideToAsc(strUrl);lRet GetFileNameAndExt(strFilePath, strFileName, strFileExt);if (lRet ! 0)goto err;curl curl_easy_init();struct curl_httppost* post NULL;struct curl_httppost* last NULL;if (curl NULL){lRet CURLE_FAILED_INIT;goto err;}curl_easy_setopt(curl, CURLOPT_URL, (char *)strCRUL.c_str()); //指定url//form-data key(path) 和 value(device_cover)curl_formadd(post, last, CURLFORM_PTRNAME, strParamName.c_str()/*parma*/, CURLFORM_PTRCONTENTS, strParamVal.c_str(), CURLFORM_END);curl_formadd(post, last, CURLFORM_PTRNAME, strParamName2.c_str(), CURLFORM_FILE, strFilePath.c_str(),CURLFORM_FILENAME, strFileName.c_str(),CURLFORM_CONTENTTYPE,image/png, CURLFORM_END);//curl_formadd(post, last, CURLFORM_PTRNAME, strParamName2.c_str(), CURLFORM_FILE, strFilePath.c_str(),CURLFORM_FILENAME, strFileName.c_str(),CURLFORM_CONTENTTYPE,image/PNG, CURLFORM_END);curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); //构造post参数 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); //绑定相应curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)strResponse); //绑定响应内容的地址res curl_easy_perform(curl); //执行请求if(res 0){curl_easy_cleanup(curl); lRet res;goto err;}else{lRet res;goto err;}lRet res;err:return lRet;
}