文档内容(Content)
MSSDK English
MSSDK 中文
MSSDK 版本发布
API 文档
集成向导
服务端文档
MSSDK 服务端接入指南
微服务API
渠道管理API
问卷星服务端接入
H5网页授权接入指南
外部网关API签名规则
应用管理API
内部网关API签名规则
签名示例
新手指导文档
联系我们

MSSDK

SDK 文档


签名示例

<p>[TOC]</p> <h3>PHP版本外部网关调用demo</h3> <pre><code class="language-php">&lt;?php //业务控制台拉取的配置 $appkey = 'xxx'; //appkey $appSecret = 'xxxx';//appsecret //顺序不能变 //详情请看:https://www.showdoc.cc/mssdk?page_id=3123995334349155 $userAgent = array ( 'platform' =&gt; 'CP', 'channel' =&gt; 'CP', 'appVersion' =&gt; '1.0.0', 'package' =&gt; 'com.cp.sdk', 'sdkVersion' =&gt; '1.0.0', 'sdkName' =&gt; 'MSSDK', 'networkType' =&gt; 'WiFi', 'deviceBrand' =&gt; 'common', 'deviceId' =&gt; '00000000', 'localTime' =&gt; '2019-01-01 00' ); //get 请求 echo PHP_EOL."---------------get-start-------------".PHP_EOL; $getUri = "/ms-player/sdk_/player/post/getAccountDetailAndSessionInfo"; $authorization="bearer 016b3fc8-4cb3-4576-8c19-ce0111291d5b"; $get_ret = (new publicGateway($appkey, $appSecret))-&gt;request($getUri, $getData=[], $authorization, $userAgent); echo $get_ret; echo PHP_EOL."---------------get-end-------------".PHP_EOL; // die; echo PHP_EOL."---------------post-start-------------".PHP_EOL; //POST 请求 $posturi = "/ms-payment/sdk_/order-api/orderState/success"; $postDataStr = '{"orderNoList":["DEV100011911221737480001"]}'; $data = json_decode($postDataStr,true); $authorization="bearer 016b3fc8-4cb3-4576-8c19-ce0111291d5b"; $post_ret = (new publicGateway($appkey, $appSecret))-&gt;request($posturi,$data, $authorization, $userAgent,"POST"); echo $post_ret; echo PHP_EOL."---------------post-end-------------".PHP_EOL; class publicGateway { //如果测试不同环境,请切换host // private const gatewayBase = 'https://pub-gw.uu.cc/public-gateway'; private const gatewayBase = 'http://dev-ms.ids111.com/dev-public-gateway'; private $appKey; private $appSecret; public function __construct($appKey, $appSecret) { $this-&gt;appKey = $appKey; $this-&gt;appSecret = $appSecret; } /** * 发起请求 * @param $url String 请求地址url * @param $requestData array 请求参数(关联数组);默认:[] * @param $requestMethod String GET/POST * @param $userAgent array userAgent(关联数组);默认:[] * @return String json结果 */ public function request($uri, $requestData=[], $authorization=null, $userAgent, $requestMethod='GET') { $signHeaderData = $this-&gt;buildSignHeaders($authorization); $signStr = $this-&gt;buildSignStr($requestMethod, $signHeaderData, $requestData); $signature = $this-&gt;sign($signStr); $curlHeadersArray = $this-&gt;buildCurlHeaders($signature, $signHeaderData, $userAgent); // echo $signStr;die; $response = $this-&gt;exec($uri, $curlHeadersArray, $requestMethod, $requestData); return $response; } public function buildCurlHeaders($signature, $signHeaderData, $userAgent){ $curlHeadersArray = array_map(function ($headerKey, $headerValue) { return $headerKey . ': ' . $headerValue; }, array_keys($signHeaderData), array_values($signHeaderData)); array_push($curlHeadersArray, "Signature: " . $signature); array_push($curlHeadersArray, "Content-Type: application/json"); $userAgentString = ''; foreach($userAgent as $key =&gt; $value){ $userAgentString .= $key.':'.$value.';'; } array_push($curlHeadersArray, "User-Agent: $userAgentString"); return $curlHeadersArray; } public function exec($uri,$curlHeadersArray,$requestMethod, $requestData){ $httpMethod = strtoupper($requestMethod); $curl = curl_init(); $gatewayUrl = self::gatewayBase.$uri; if ($httpMethod == 'GET') { $gatewayUrl = self::gatewayBase.$uri.'?'.http_build_query($requestData); } curl_setopt($curl, CURLOPT_URL, $gatewayUrl); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST,$httpMethod); curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeadersArray); if ('POST' == $httpMethod) { curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($requestData)); } $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { throw new Exception("cURL Error #:" . $err); } else { return $response; } } public function sign($signStr){ $signStrFormat = '%s&amp;%s&amp;%s'; $signStr = sprintf($signStrFormat, $this-&gt;appSecret, $signStr, $this-&gt;appSecret); //md5后 进行urlencode $signature = urlencode(md5($signStr)); return $signature; } /** * 构造签名字符串 */ public function buildSignStr($requestMethod, $signHeaderData, $requestData) { if ('post' == strtolower($requestMethod)) { if (empty($requestData)){ $requestJsonStr = "{}"; } else { $requestJsonStr = json_encode($requestData); } $postData = ['requestBody' =&gt; $requestJsonStr]; $data = array_merge($signHeaderData, $postData); } else { //合并请求参数和请求头 $data = array_merge($signHeaderData, $requestData); } // print_r($data);die; //字典排序 ksort($data); // 拼成url请求参数Key1=value1&amp; Key2=value2&amp; Key3=value3&amp;………… $signStr = urldecode(http_build_query($data)); return $signStr; } /** * 生成请求header(不包含signatrue) */ private function buildSignHeaders($authorization) { $timeStamp = round(microtime(true) * 1000); $nonce = substr(md5(rand()),4,10); $signHeaders = [ "AppKey" =&gt; $this-&gt;appKey, "Nonce" =&gt; $nonce, "Timestamp" =&gt; $timeStamp, ]; if(!is_null($authorization) &amp;&amp; strlen(trim($authorization))&gt;1){ $signHeaders['Authorization'] = $authorization; } return $signHeaders; } } </code></pre> <h3>PHP版本内部网关调用demo</h3> <pre><code class="language-php">&lt;?php //业务控制台应用配置 $appkey = 'xxxxx'; //appkey $appSecret = 'xxx';//appsecret //get 请求 echo PHP_EOL."---------------get-------------".PHP_EOL; //如:调用应用管理相关接口 $getUri = "/ms-app-manage/platform/all/appWithBasic"; $get_ret = (new innerGateway($appkey, $appSecret))-&gt;request($getUri); echo $get_ret; echo PHP_EOL."---------------post-------------".PHP_EOL; //POST 请求 //eg: 更新玩家信息接口 $posturi = "/ms-player/admin/player/updatePlayerInfo"; $postDataStr = '{ "accessToken":"282d2be3-cfc6-445a-a57a-31137e3916b1", "city":"深圳", "birthday":"2015-09-12", "country":"中国", "image":"guangzhou.myqcloud.com/902292/20190726164540026/fKfNO4pvNv7IAbiMtLKN.jpg", "nickname":"哈哈", "province":"广东" }'; $data = json_decode($postDataStr,true); $post_ret = (new innerGateway($appkey, $appSecret))-&gt;request($posturi,$data, "POST"); echo $post_ret; class innerGateway { //如果测试不同环境,请切换host private const gatewayBase = 'https://internal-gw.uu.cc/internal-gateway'; private $appKey; private $appSecret; public function __construct($appKey, $appSecret) { $this-&gt;appKey = $appKey; $this-&gt;appSecret = $appSecret; } /** * 发起请求 * @param $url String 请求地址url * @param $requestData array 请求参数(关联数组);默认:[] * @param $requestMethod String GET/POST * @return String json结果 */ public function request($uri, $requestData=[], $requestMethod='GET') { $signHeaderData = $this-&gt;buildSignHeaders(); $signStr = $this-&gt;buildSignStr($requestMethod, $signHeaderData, $requestData); $signature = $this-&gt;sign($signStr); $curlHeadersArray = $this-&gt;buildCurlHeaders($signature, $signHeaderData); // echo $signStr;die; $response = $this-&gt;exec($uri, $curlHeadersArray, $requestMethod, $requestData); return $response; } public function buildCurlHeaders($signature, $signHeaderData){ $curlHeadersArray = array_map(function ($headerKey, $headerValue) { return $headerKey . ': ' . $headerValue; }, array_keys($signHeaderData), array_values($signHeaderData)); array_push($curlHeadersArray, "Signature: " . $signature); array_push($curlHeadersArray, "Content-Type: application/json"); return $curlHeadersArray; } public function exec($uri,$curlHeadersArray,$requestMethod, $requestData){ $httpMethod = strtoupper($requestMethod); $curl = curl_init(); $gatewayUrl = self::gatewayBase.$uri; if ($httpMethod == 'GET') { $gatewayUrl = self::gatewayBase.$uri.'?'.http_build_query($requestData); } curl_setopt($curl, CURLOPT_URL, $gatewayUrl); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST,$httpMethod); curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeadersArray); if ('POST' == $httpMethod) { curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($requestData)); } $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { throw new Exception("cURL Error #:" . $err); } else { return $response; } } public function sign($signStr){ $signStrFormat = '%s&amp;%s&amp;%s'; $signStr = sprintf($signStrFormat, $this-&gt;appSecret, $signStr, $this-&gt;appSecret); //md5后 进行urlencode $signature = urlencode(md5($signStr)); return $signature; } /** * 构造签名字符串 */ public function buildSignStr($requestMethod, $signHeaderData, $requestData) { if ('post' == strtolower($requestMethod)) { if (empty($requestData)){ $requestJsonStr = "{}"; } else { $requestJsonStr = json_encode($requestData); } $postData = ['requestBody' =&gt; $requestJsonStr]; $data = array_merge($signHeaderData, $postData); } else { //合并请求参数和请求头 $data = array_merge($signHeaderData, $requestData); } // print_r($data);die; //字典排序 ksort($data); // 拼成url请求参数Key1=value1&amp; Key2=value2&amp; Key3=value3&amp;………… $signStr = urldecode(http_build_query($data)); return $signStr; } /** * 生成请求header(不包含signatrue) */ private function buildSignHeaders() { $timeStamp = round(microtime(true) * 1000); $nonce = substr(md5(rand()),4,10); $signHeaders = [ "AppKey" =&gt; $this-&gt;appKey, "Nonce" =&gt; $nonce, "Timestamp" =&gt; $timeStamp, ]; return $signHeaders; } } </code></pre> <h3>Java版本签名示例</h3> <h4>参数构造工具类</h4> <pre><code class="language-java">package com.tc.sign; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; public class ParameterUtil { /** * 将Map组装成待签名数据。 * 待签名的数据必须按照一定的顺序排列 * @param params * @return */ public static String getSignData(Map&lt;String, String&gt; params) { StringBuffer content = new StringBuffer(); // 按照key做排序 List&lt;String&gt; keys = new ArrayList&lt;String&gt;(params.keySet()); Collections.sort(keys); boolean isFirst = true; for (int i = 0; i &lt; keys.size(); i++) { String key = (String) keys.get(i); if ("sign".equals(key)||"sign_type".equals(key)) { continue; } String value = (String) params.get(key); if (value != null &amp;&amp; value.length() &gt;0) { content.append((isFirst ? "" : "&amp;") + key + "=" + value); isFirst = false; } } return content.toString(); } /** * 将Map中的数据组装成url * @param params * @return * @throws UnsupportedEncodingException */ public static String mapToUrl(Map&lt;String, String&gt; params) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); boolean isFirst = true; for (String key : params.keySet()) { String value = params.get(key); if (isFirst) { sb.append(key + "=" + URLEncoder.encode(value, "utf-8")); isFirst = false; } else { if (value != null) { sb.append("&amp;" + key + "=" + URLEncoder.encode(value, "utf-8")); } else { sb.append("&amp;" + key + "="); } } } return sb.toString(); } /** * 取得URL中的参数值。 * &lt;p&gt;如不存在,返回空值。&lt;/p&gt; * * @param url * @param name * @return */ public static String getParameter(String url, String name) { if (name == null || name.equals("")) { return null; } name = name + "="; int start = url.indexOf(name); if (start &lt; 0) { return null; } start += name.length(); int end = url.indexOf("&amp;", start); if (end == -1) { end = url.length(); } return url.substring(start, end); } }</code></pre> <h4>生成MD5工具类</h4> <pre><code class="language-java">package com.tc.sign; import java.io.UnsupportedEncodingException; import java.security.SignatureException; import java.util.HashMap; import java.util.Map; import org.apache.commons.codec.digest.DigestUtils; public class MD5Util{ public static String sign(String content, String secret) throws Exception { String tosign = secret + "&amp;" + (content == null ? "" : content) + "&amp;" + secret; try { return DigestUtils.md5Hex(getContentBytes(tosign, "utf-8")); } catch (UnsupportedEncodingException e) { throw new SignatureException("MD5签名发生异常!", e); } } }</code></pre> <h3>C++版本签名示例</h3> <p><strong>sign.h</strong></p> <pre><code>#ifndef SIGN_H_ #define SIGN_H_ #include&lt;iostream&gt; #include&lt;string&gt; #include&lt;map&gt; #include&lt;stdlib.h&gt; #include&lt;stdio.h&gt; using namespace std; class sign{ public: sign(const string appKey,const string appSecrect); ~sign(); bool generateSignature(map&lt;string,string&gt; mParam,string &amp;signature); bool checkSignature(map&lt;string,string&gt; mParam,const string &amp;signature); protected: string md5(string data); private: string m_strAppKey; string m_strAppSecrect; }; #endif /*SIGN_H_*/ </code></pre> <p><strong>sign.cpp</strong></p> <p>```sign.cpp</p> <h1>include &quot;sign.h&quot;</h1> <h1>include<algorithm></h1> <h1>include&lt;openssl/md5.h&gt;</h1> <h1>include<string.h></h1> <p>sign::sign(const string appKey,const string appSecrect) { m_strAppKey = appKey; m_strAppSecrect = appSecrect; }</p> <p>sign::~sign() {</p> <p>}</p> <p>bool sign::generateSignature(map&lt;string,string&gt; mParam,string &amp;signature) { if(mParam.empty() || m_strAppSecrect.empty()){ return false; }</p> <pre><code>string content=m_strAppSecrect; map&lt;string,string&gt;::iterator iter; for(iter=mParam.begin();iter !=mParam.end();++iter){ //排查签名字段 if(iter-&gt;first == "Signature"){ continue; } content.append("&amp;"); content.append(iter-&gt;first); content.append("="); content.append(iter-&gt;second); } content.append("&amp;"); content.append(m_strAppSecrect); signature= md5(content); cout&lt;&lt;"content:" &lt;&lt; content &lt;&lt; endl; cout &lt;&lt; "signature:" &lt;&lt; signature &lt;&lt; endl; return true;</code></pre> <p>}</p> <p>string sign::md5(string data) { MD5_CTX ctx; unsigned char md[16]; char buf[33]={'\0'}; char tmp[3]={'\0'}; int i = 0;</p> <pre><code>MD5_Init(&amp;ctx); //初始化一个MD5_CTX这样的结构体 MD5_Update(&amp;ctx,data.c_str(),strlen(data.c_str())); //更新这块区域,防止引用非法数据 MD5_Final(md,&amp;ctx); //最后把ctx中的数据按照MD5算法生成16位的MD5码,存放到md中 string md5Value; for( i=0; i&lt;sizeof(md); i++ ){ sprintf(tmp,"%02X",md[i]); md5Value.append(tmp); } return md5Value;</code></pre> <p>}</p> <p>bool sign::checkSignature(map&lt;string,string&gt; mParam,const string &amp;signature) { string strSign; if(generateSignature(mParam,strSign)){ cout&lt;&lt;&quot;strSign:&quot; &lt;&lt; strSign &lt;&lt; &quot;signature:&quot; &lt;&lt; signature &lt;&lt; endl; return strSign == signature; }</p> <pre><code>return false;</code></pre> <p>}</p> <pre><code>**manager_curl.h ** </code></pre> <p>/*</p> <ul> <li>curl的封装,有以下操作:</li> <li>1.设置服务器参数</li> <li>2.发送信息:get、post、put、delete</li> <li>3.上传文件处理</li> <li>4.下载文件 */</li> </ul> <h1>ifndef MANAGER_CURL<em>H</em></h1> <h1>define MANAGER_CURL<em>H</em></h1> <h1>include <stdio.h></h1> <h1>include <stdlib.h></h1> <h1>include &lt;curl/curl.h&gt;</h1> <h1>include <string></h1> <h1>include &quot;manager_lock.h&quot;</h1> <p>//for test</p> <h1>define EPRINT printf</h1> <h1>define DPRINT printf</h1> <p>/*</p> <ul> <li>宏定义发送方法 */ <h1>define METHOD_GET 0 //get方法</h1> <h1>define METHOD_POST 1 //post方法</h1> <h1>define METHOD_PUT 2 //put方法</h1> <h1>define METHOD_DELETE 3 //delete方法</h1></li> </ul> <p>/*</p> <ul> <li>宏定义数据格式 */ <h1>define FORMAT_DEFAULT 0 //默认数据格式</h1> <h1>define FORMAT_XML 1 //xml数据格式</h1> <h1>define FORMAT_JSON 2 //json数据格式</h1></li> </ul> <p>/*</p> <ul> <li>宏定义超时时间 */ <h1>define CONNECT_DEFAULT_TIMEOUT 10 //连接最长时间</h1> <h1>define DEFAULT_TIMEOUT 600 //传输最长时间</h1></li> </ul> <p>class ClusterCurl {</p> <p>private: CURL<em> m_pCurl; //curl指针 struct curl_slist</em> m_pHeaders; //http消息头 std::string m_sIP; //curl请求的ip unsigned int m_nPort; //curl请求ip的端口 std::string m_sUser; //需要对方验证时使用,请求对方需要的用户名 std::string m_sPwd; //需要对方验证时使用,请求对方需要的密码 std::string m_sUrlPath; //url路径 static bool s_bGlobalInitStatus; //判断是否已进行全局初始化,0表示未初始化,1表示已经初始化 static MutexLock s_MutexLock; //mutex锁对象 unsigned int m_contect_timeout; //连接最长时间 unsigned int m_timeout; //传输最长时间</p> <p>public:</p> <pre><code>ClusterCurl(); ClusterCurl(const std::string&amp; sIP, const unsigned int nPort, const std::string&amp; sUser, const std::string&amp; sPwd); ~ClusterCurl(); // 设置等待连接最长时间 void setConnectTimeout(unsigned int nTime); // 设置传输最长时间 void setTimeout(unsigned int nTime); //设置服务器参数 void setServer(const std::string&amp; sIP, const unsigned int nPort, const std::string&amp; sUser, const std::string&amp; sPwd); //设置URL路径 void setUrlPath(const std::string&amp; sUrlPath); //设置请求头 void setHeaders(const std::string &amp;sHeader); //发送消息发送方式 int sendMsg(const std::string&amp; sMsg, const int nMethod, const int nFormat, std::string&amp; sRec); //下载文件 int downloadFile(const std::string&amp; sFileName, const int nFormat); //从文件中读取内容post出去 int uploadFileContent(const std::string&amp; sFileName, const int nFormat, std::string&amp; sRec); //上传文件 int uploadFile(const std::string&amp; sFileFullname, std::string&amp; sRec); //进行所有CURL开始之前,全局变量初始化,放在主线程中 static int globalInit(); //全局资源释放,行所有CURL结束之前,放在主线程中 static int globalCleanup(); //对单一curl资源进行初始化,不封装在构造函数的好处是,可以对curl初始化异常时进行处理 int initCurlResource(); //对单一curl资源进行释放,可用可不用, 不用则留给类析构释放, 使用好处时,使用者可以对异常进行处理 int releaseCurlResource();</code></pre> <p>private:</p> <pre><code>//设置请求用户名和密码 int setUserPwd(); //设置数据格式 int setDataFormat(const int nFormat); //回调函数,将文件内容读取到缓存中 static size_t httpReadFile(void* buffer, size_t size, size_t nmemb, void* file); //回调函数,将缓存内容写到文件中 static size_t httpWriteFile(void* buffer, size_t size, size_t nmemb, void* file); //回调函数,将返回缓存数据写出 static size_t httpDataWriter(void* buffer, size_t size, size_t nmemb, void* content); //通过get的方式发送信息 int getMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec); //通过post的方式发送信息 int postMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec); //通过put的方式发送信息 int putMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec); //通过delete进行操作 int deleteMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec); //curl一些公用操作 int messagePublicMethod(const int nFormat); //curl返回值处理 int dealResCode(const CURLcode res); //从文件全路径中获取文件名指针 const char* getFileName(const char *path);</code></pre> <p>};</p> <h1>endif //MANAGER_CURL<em>H</em></h1> <pre><code>**manager_curl.cpp** </code></pre> <p>/*</p> <ul> <li>curl的封装的具体实现,有以下操作:</li> <li>1.设置服务器参数</li> <li>2.发送信息:get、post、put、delete</li> <li>3.上传文件处理</li> <li>4.下载文件 */</li> </ul> <h1>include <string.h></h1> <h1>include &lt;sys/stat.h&gt;</h1> <h1>include <errno.h></h1> <h1>include &quot;manager_curl.h&quot;</h1> <p>bool ClusterCurl::s_bGlobalInitStatus = 0; MutexLock ClusterCurl::s_MutexLock;</p> <p>/*</p> <ul> <li>默认构造函数 */ ClusterCurl::ClusterCurl():m_pCurl(NULL), m_pHeaders(NULL), m_sIP(), m_nPort(), m_sUser(), m_sPwd(), m_contect_timeout(0), m_timeout(0) {</li> </ul> <p>}</p> <p>/*</p> <ul> <li>构造函数,进行成员变量初始化</li> <li>参数1:请求的ip地址</li> <li>参数2:请求ip地址的端口</li> <li>参数3:对方验证用户名</li> <li>参数4:对方验证密码 */ ClusterCurl::ClusterCurl(const std::string&amp; sIP, const unsigned int nPort, const std::string&amp; sUser, const std::string&amp; sPwd) :m_pCurl(NULL), m_pHeaders(NULL), m_sIP(sIP), m_nPort(nPort), m_sUser(sUser), m_sPwd(sPwd), m_contect_timeout(0), m_timeout(0) {</li> </ul> <p>}</p> <p>/*</p> <ul> <li> <p>析构函数,进行释放资源 */ ClusterCurl::~ClusterCurl() { try { if(NULL != this-&gt;m_pHeaders) { curl_slist_free_all(this-&gt;m_pHeaders); this-&gt;m_pHeaders = NULL; }</p> <pre><code>if(NULL != this-&gt;m_pCurl) { releaseCurlResource(); }</code></pre> <p>} catch(...) //吞下异常,防止异常逃离析构函数 { EPRINT(&quot;~ClusterCurl api exception error(%d) \n&quot;, errno); }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>进行所有CURL开始之前的,全局变量初始化,放在主线程中</li> <li> <p>返回值为int, 0表示成功,其他表示失败 */ int ClusterCurl::globalInit() { int nCode = -1; int nLockJudge = -1; int nUnlockJudge = -1;</p> <p>try { nLockJudge = ClusterCurl::s_MutexLock.lock(); nCode = nLockJudge; if(0 != nCode) { EPRINT(&quot;globalInit mutex lock error(%d)\n&quot;, errno); return nCode; }</p> <pre><code>if(0 == s_bGlobalInitStatus) { if(CURLE_OK == curl_global_init(CURL_GLOBAL_ALL)) { //返回成功 s_bGlobalInitStatus = 1; } else { EPRINT("globalInit error(%d)\n", errno); nCode = -1; //CURL全局资源初始化失败 } } nUnlockJudge = ClusterCurl::s_MutexLock.unlock(); return nCode;</code></pre> <p>} catch(...) { if(0 == nLockJudge &amp;&amp; 0 != nUnlockJudge) { ClusterCurl::s_MutexLock.unlock(); }</p> <pre><code>EPRINT("global init api exception(%d)\n", errno); return -1; //异常接口</code></pre> <p>}</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>进行所有CURL开始结束的,全局变量初始化,放在主线程中</li> <li> <p>返回值为int, 0表示成功,其他表示失败 */ int ClusterCurl::globalCleanup() { int nLockJudge = -1; int nUnlockJudge = -1; int nCode = -1;</p> <p>try { nLockJudge = ClusterCurl::s_MutexLock.lock(); nCode = nLockJudge; if(0 != nCode) { EPRINT(&quot;globalCleanup mutex lock error(%d)\n&quot;, errno); return nCode; }</p> <pre><code>if(1 == s_bGlobalInitStatus) { curl_global_cleanup(); s_bGlobalInitStatus = 0; } nUnlockJudge = ClusterCurl::s_MutexLock.unlock(); nCode = nUnlockJudge; return nCode;</code></pre> <p>} catch(...) { if(0 == nLockJudge &amp;&amp; 0 != nUnlockJudge) { ClusterCurl::s_MutexLock.unlock(); } EPRINT(&quot;globalCleanup api exception(%d)\n&quot;, errno); return -1; //异常接口 }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>进行单个线程CURL简单资源进行初始化</li> <li>返回值int, 0表示成功, 其它表示失败 */ int ClusterCurl::initCurlResource() { this-&gt;m_pCurl = curl_easy_init(); if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;curl easy init failure \n&quot;); return -1; } else { return 0; }</li> </ul> <p>}</p> <p>/*</p> <ul> <li>进行单个线程CURL简单资源进行释放</li> <li> <p>返回值为int, 0表示成功,其他表示失败 */ int ClusterCurl::releaseCurlResource() { //判断参数的合法性 if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;releaseCurlResource curl ptr is null \n&quot;); return -1; //CURL指针为NULL }</p> <p>//释放curl指针 curl_easy_cleanup(this-&gt;m_pCurl); this-&gt;m_pCurl = NULL;</p> <p>return 0; }</p> </li> </ul> <p>/*</p> <ul> <li>设置传输的用户和密码验证</li> <li>参数1:curl指针,通过此指针进行设置用户密码操作</li> <li> <p>返回值int, 0表示成功,其他表示失败 */ int ClusterCurl::setUserPwd() { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;setUserPwd curl ptr is null \n&quot;); return -1; //CURL指针为NULL }</p> <p>std::string sUserPwd; if((!(this-&gt;m_sUser.empty())) &amp;&amp; (!(this-&gt;m_sPwd.empty()))) { sUserPwd = this-&gt;m_sUser + &quot;:&quot; + this-&gt;m_sPwd; curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_USERPWD, (char*)sUserPwd.c_str()); } return 0; }</p> </li> </ul> <p>/*</p> <ul> <li>设置等待连接最长时间</li> <li>参数1:最长时间秒数 */ void ClusterCurl::setConnectTimeout(unsigned int nTime) { this-&gt;m_contect_timeout = nTime; }</li> </ul> <p>/*</p> <ul> <li>设置传输最长时间</li> <li>参数1:最长时间秒数 */ void ClusterCurl::setTimeout(unsigned int nTime) { this-&gt;m_timeout = nTime; }</li> </ul> <p>//设置请求头 void ClusterCurl::setHeaders(const std::string &amp;sHeader) { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;setDataFormat curl ptr is null \n&quot;); return; //CURL指针为NULL }</p> <pre><code> //非空设置相应格式,空则不设置 if(NULL == this-&gt;m_pHeaders){ this-&gt;m_pHeaders = curl_slist_append(NULL, (char*)sHeader.c_str()); } else{ this-&gt;m_pHeaders = curl_slist_append(this-&gt;m_pHeaders, (char*)sHeader.c_str()); } if(NULL == this-&gt;m_pHeaders) { EPRINT("setHeaders set format error(%d) \n", errno); return; }</code></pre> <p>}</p> <p>/*</p> <ul> <li>宏定义数据格式字符串 */ //XML格式 <h1>define XML_FORMAT_STRING &quot;Content-Type: application/xml;charset=UTF-8&quot;</h1> <p>//JSON格式</p> <h1>define JSON_FORMAT_STRING &quot;Content-Type: application/json;charset=UTF-8&quot;</h1></li> </ul> <p>/*</p> <ul> <li>设置数据格式</li> <li>参数1:CURL指针</li> <li>参数2:发送数据格式,0默认,1为xml,2为json</li> <li> <p>返回值int,0表示成功,其它表示失败 */ int ClusterCurl::setDataFormat(const int nFormat) { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;setDataFormat curl ptr is null \n&quot;); return -1; //CURL指针为NULL }</p> <p>std::string sFormatStr; if(FORMAT_XML == nFormat) { sFormatStr = XML_FORMAT_STRING; } else if(FORMAT_JSON == nFormat) { sFormatStr = JSON_FORMAT_STRING; }</p> <p>if(!sFormatStr.empty()) { //非空设置相应格式,空则不设置 if(NULL == this-&gt;m_pHeaders){ this-&gt;m_pHeaders = curl_slist_append(NULL, (char<em>)sFormatStr.c_str()); } else { this-&gt;m_pHeaders = curl_slist_append(this-&gt;m_pHeaders, (char</em>)sFormatStr.c_str()); }</p> <pre><code>if(NULL == this-&gt;m_pHeaders) { EPRINT("setDataFormat set format error(%d) \n", errno); return -1; } curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_HTTPHEADER, this-&gt;m_pHeaders);</code></pre> <p>}</p> <p>return 0; }</p> </li> </ul> <p>/*</p> <ul> <li>设置服务器参数</li> <li>参数1:服务器ip</li> <li>参数2:服务器ip相关端口</li> <li>参数3:服务器用户名</li> <li>参数4:服务器密码 */ void ClusterCurl::setServer(const std::string&amp; sIP, const unsigned int nPort, const std::string&amp; sUser, const std::string&amp; sPwd) { this-&gt;m_sIP = sIP; this-&gt;m_nPort = nPort; this-&gt;m_sUser = sUser; this-&gt;m_sPwd = sPwd; }</li> </ul> <p>/*</p> <ul> <li>设置URL路径</li> <li>参数1:URL路径 */ void ClusterCurl::setUrlPath(const std::string&amp; sUrlPath) { this-&gt;m_sUrlPath = sUrlPath; }</li> </ul> <p>/*</p> <ul> <li>回调函数,处理返回的数据</li> <li>参数1:缓存存放</li> <li>参数2:缓存块数</li> <li>参数3:缓存每块大小</li> <li>参数4:WRITEDATA对应的数据流</li> <li>返回值, 数据所占字节数 <em>/ size_t ClusterCurl::httpDataWriter(void</em> buffer, size_t size, size_t nmemb, void<em> content) { long totalSize = size</em>nmemb; std::string<em> symbolBuffer = (std::string</em>)content; if(symbolBuffer) { symbolBuffer-&gt;append((char <em>)buffer, ((char</em>)buffer)+totalSize); return totalSize; } else { EPRINT(&quot;ClusterCurl httpDataWriter data error(%d) \n&quot;, errno); return 0; }</li> </ul> <p>}</p> <p>/*</p> <ul> <li>回调函数,上传文件处理,读文件</li> <li>参数1:缓存存放</li> <li>参数2:缓存块数</li> <li>参数3:缓存每块大小</li> <li>参数4:READDATA对应的数据流</li> <li>返回值,数据所占字节数 <em>/ size_t ClusterCurl::httpReadFile(void</em> buffer, size_t size, size_t nmemb, void<em> file) { return fread(buffer, size, nmemb, (FILE </em>)file); }</li> </ul> <p>/*</p> <ul> <li>回调函数,下载文件处理,写文件</li> <li>参数1:缓存存放</li> <li>参数2:缓存块数</li> <li>参数3:缓存每块大小</li> <li>参数4:WRITEDATA对应的数据流</li> <li>返回值,数据所占字节数 <em>/ size_t ClusterCurl::httpWriteFile(void</em> buffer, size_t size, size_t nmemb, void<em> file) { return fwrite(buffer, size, nmemb, (FILE </em>)file); }</li> </ul> <p>/*</p> <ul> <li>数据发送方式</li> <li>参数1:要发送的数据</li> <li>参数2:发送的方法:0使用GET, 1使用POST, 2使用PUT, 3使用DELETE</li> <li>参数3:数据头格式,0表示默认,1表示xml,2为json</li> <li>参数4:返回的数据信息</li> <li>返回值int, 0表示成功, 1表示超时,其他表示失败 */ int ClusterCurl::sendMsg(const std::string&amp; sMsg, const int nMethod, const int nFormat, std::string&amp; sRec) { int nCode = -1; sRec = &quot;&quot;; //清空数据 switch(nMethod) { case METHOD_GET: //使用GET方法传送数据 { nCode = getMsg(sMsg, nFormat, sRec); return nCode; } case METHOD_POST: //使用POST方法传送数据 { nCode = postMsg(sMsg, nFormat, sRec); return nCode; } case METHOD_PUT: //使用PUT方法传送数据 { nCode = putMsg(sMsg, nFormat, sRec); return nCode; } case METHOD_DELETE: //使用DELETE方法传送数据 { nCode = deleteMsg(sMsg, nFormat, sRec); return nCode; } default: { EPRINT(&quot;sendMsg method error\n&quot;); return -1; } } }</li> </ul> <p>/*</p> <ul> <li>CURL公共操作</li> <li>参数1:curl指针,通过此指针进行相关设置</li> <li> <p>返回值int,0表示成功,其他表示失败 */ int ClusterCurl::messagePublicMethod(const int nFormat) { int nCode = -1; try { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;messagePublicMethod curl ptr is null\n&quot;); return -1; //CURL指针为NULL }</p> <pre><code>//参数合法性检测 if(0 &gt; nFormat) { EPRINT("messagePublicMethod params error, nFormat=%d \n", nFormat); return -1; //CURL指针为NULL } //指定url if(this-&gt;m_sIP.empty()) { EPRINT("messagePublicMethod ip is empty\n"); return -1; } std::string sUrl; sUrl = sUrl + "http://" + this-&gt;m_sIP + this-&gt;m_sUrlPath; DPRINT("sUrl: %s\n", sUrl.c_str()); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_URL, (char*)sUrl.c_str()); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_PORT, this-&gt;m_nPort); //设置用户名和密码 nCode = setUserPwd(); if(0 != nCode) { EPRINT("messagePublicMethod setUserPwd error(%d) \n", errno); return -1; } //设置数据格式 nCode = setDataFormat(nFormat); if(0 != nCode) { EPRINT("messagePublicMethod setDataFormat error(%d) \n", errno); return -1; } //禁用掉alarm这种超时 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_NOSIGNAL, 1); //设置超时时间 if(0 &gt;= this-&gt;m_contect_timeout) { this-&gt;m_contect_timeout = CONNECT_DEFAULT_TIMEOUT; } curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_CONNECTTIMEOUT, this-&gt;m_contect_timeout); if(0 &gt;= this-&gt;m_timeout) { this-&gt;m_timeout = DEFAULT_TIMEOUT; } curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_TIMEOUT, this-&gt;m_timeout); /* 第一:默认情况下libcurl完成一个任务以后,出于重用连接的考虑不会马上关闭,如果每次目标主机不一样,这里禁止重连接 第二:每次执行完curl_easy_perform,licurl会继续保持与服务器的连接。接下来的请求可以使用这个连接而不必创建新的连接,如果目标主机是同一个的话。 这样可以减少网络开销。 */ curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_FORBID_REUSE, 1); return 0;</code></pre> <p>} catch(...) { EPRINT(&quot;messagePublicMethod api exception(%d)\n&quot;, errno); return -1; //发送信息公共接口异常 } }</p> </li> </ul> <p>/*</p> <ul> <li>curl返回值处理</li> <li>参数1: curl返回码</li> <li> <p>返回值int, 0表示成功, 1表示超时, 其他表示失败 <em>/ int ClusterCurl::dealResCode(const CURLcode res) { //输出返回码代表的意思 int nCode = 0; const char</em> pRes = NULL; pRes = curl_easy_strerror(res); DPRINT(&quot;%s\n&quot;,pRes);</p> <p>//http返回码 long lResCode = 0; curl_easy_getinfo(this-&gt;m_pCurl, CURLINFO_RESPONSE_CODE, &amp;lResCode);</p> <p>if(CURLE_OK != res || 200 != lResCode) { //curl传送失败 if(CURLE_OPERATION_TIMEOUTED == res) { nCode = 1; //超时返回1 } else { nCode = -1; //其它错误返回-1 } EPRINT(&quot;curl send msg error: pRes=%s, lResCode=%ld \n&quot;, pRes, lResCode); }</p> <p>return nCode; }</p> </li> </ul> <p>/*</p> <ul> <li>通过put的方式操作</li> <li>参数1:要发送的数据</li> <li>参数2: 数据头格式,0为默认,1为xml,2为json</li> <li>参数3:返回的数据</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 */ int ClusterCurl::putMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec) { CURLcode res = CURLE_OK; int nCode = -1;</p> <p>try { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;putMsg curl ptr is null\n&quot;); return -1; //CURL指针为NULL }</p> <pre><code>//发送数据,以及发送方式 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_CUSTOMREQUEST, "PUT"); if(sMsg.empty()) { curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POSTFIELDS, ""); } else { curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POSTFIELDS, (char*)sMsg.c_str()); } //CURL公共操作方式 nCode = messagePublicMethod(nFormat); if(0 != nCode) { EPRINT("putMsg call messagePublicMethod error(%d) \n", errno); return -1; } // 设置回调函数 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, (void*)&amp;sRec); res = curl_easy_perform(this-&gt;m_pCurl); //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } return nCode;</code></pre> <p>} catch(...) { EPRINT(&quot;putMsg api exception(%d)\n&quot;, errno); return -1; // 接口异常 } }</p> </li> </ul> <p>/*</p> <ul> <li>通过delete的方式操作</li> <li>参数1:要发送的数据,此方式可空</li> <li>参数2:数据头格式,0为默认,1为xml,2为json</li> <li>参数3:数据头格式,0表示默认,1表示xml,2为json</li> <li>参数4:返回的数据</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 */ int ClusterCurl::deleteMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec) { CURLcode res = CURLE_OK; int nCode = -1;</p> <p>try { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;deleteMsg curl ptr is null\n&quot;); return -1; //CURL指针为NULL }</p> <pre><code>//发送数据,以及发送方式 curl_easy_setopt(this-&gt;m_pCurl,CURLOPT_CUSTOMREQUEST,"DELETE"); //CURL公共操作方式 nCode = messagePublicMethod(nFormat); if(0 != nCode) { EPRINT("deleteMsg call messagePublicMethod error(%d) \n", errno); return -1; } // 设置回调函数 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, (void*)&amp;sRec); res = curl_easy_perform(this-&gt;m_pCurl); //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } return nCode;</code></pre> <p>} catch(...) { EPRINT(&quot;deleteMsg api exception(%d)\n&quot;, errno); return -1; //接口异常 }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>通过post的方式操作</li> <li>参数1:要发送的数据</li> <li>参数2:数据头格式,0为默认,1为xml,2为json</li> <li>参数3:数据头格式,0表示默认,1表示xml,2为json</li> <li>参数4:返回的数据</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 */ int ClusterCurl::postMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec) { CURLcode res = CURLE_OK; int nCode = -1;</p> <p>try { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;postMsg curl ptr is null\n&quot;); return -1; //CURL指针为NULL }</p> <pre><code>//发送数据,以及发送方式 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POST, 1); if(sMsg.empty()) { curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POSTFIELDS, ""); } else { curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POSTFIELDS, (char*)sMsg.c_str()); } //CURL公共操作方式 nCode = messagePublicMethod(nFormat); if(0 != nCode) { EPRINT("postMsg call messagePublicMethod error(%d) \n", errno); return -1; } // 设置回调函数 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, (void*)&amp;sRec); res = curl_easy_perform(this-&gt;m_pCurl); //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } return nCode;</code></pre> <p>} catch(...) { EPRINT(&quot;postMsg api exception(%d)\n&quot;, errno); return -1; // 接口异常 }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>通过get的方式操作</li> <li>参数1:要发送的数据, 此方式可为空</li> <li>参数2:数据头格式,0表示默认,1表示xml,2为json</li> <li>参数3:返回的数据</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 */ int ClusterCurl::getMsg(const std::string&amp; sMsg, const int nFormat, std::string&amp; sRec) { CURLcode res = CURLE_OK; int nCode = -1;</p> <p>try { if(NULL == this-&gt;m_pCurl) { EPRINT(&quot;getMsg curl ptr is null\n&quot;); return -1; //CURL指针为NULL }</p> <pre><code>//设定传输方式 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_HTTPGET, 1); //CURL公共操作方式 nCode = messagePublicMethod(nFormat); if(0 != nCode) { EPRINT("getMsg call messagePublicMethod error(%d) \n", errno); return -1; } // 设置回调函数 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, (void*)&amp;sRec); res = curl_easy_perform(this-&gt;m_pCurl); //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } return nCode;</code></pre> <p>} catch(...) { EPRINT(&quot;getMsg api exception(%d)\n&quot;, errno); return -1; //接口异常 }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>下载文件</li> <li>参数1:文件存放名</li> <li>参数2:数据头格式,0表示默认,1表示xml,2为json</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 <em>/ int ClusterCurl::downloadFile(const std::string&amp; sFileName, const int nFormat) { CURLcode res = CURLE_OK; FILE</em> pFile = NULL; int nCode = -1;</p> <p>try { if(sFileName.empty()) { EPRINT(&quot;downloadFile filename is empty\n&quot;); return -1; //文件名为空 } pFile = fopen((char<em>)sFileName.c_str(), &quot;w&quot;); //打开文件,返回结果用文件存储 if (NULL == pFile) { EPRINT(&quot;downloadFile open file error(%d), %s\n&quot;, errno, (char</em>)sFileName.c_str()); return -1; //打开文件失败 }</p> <pre><code>//设定传输方式 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_HTTPGET, 1); //CURL公共操作方式 nCode = messagePublicMethod(nFormat); if(0 != nCode) { if(NULL != pFile) { fclose(pFile); pFile = NULL; } EPRINT("downloadFile call messagePublicMethod error(%d) \n", errno); return -1; } // 设置回调函数 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpWriteFile); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, pFile); res = curl_easy_perform(this-&gt;m_pCurl); //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } //关闭文件 fclose(pFile); pFile = NULL; return nCode;</code></pre> <p>} catch(...) { if(NULL != pFile) { fclose(pFile); pFile = NULL; } EPRINT(&quot;downloadFile api exception(%d)\n&quot;, errno); return -1; //接口异常 }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>从文件中读取内容post出去</li> <li>参数1:文件名</li> <li>参数2:返回数据</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 <em>/ int ClusterCurl::uploadFileContent(const std::string&amp; sFileName, const int nFormat, std::string&amp; sRec) { CURLcode res = CURLE_OK; FILE</em> pFile = NULL; struct stat file_info; curl_off_t fsize; int nCode = 0;</p> <p>try { if(sFileName.empty()) { EPRINT(&quot;uploadFileContent filename is empty\n&quot;); return -1; //文件名为空 }</p> <pre><code>if(stat((char*)sFileName.c_str(), &amp;file_info)) //文件大小 { EPRINT("uploadFileContent get file info error(%d), %s\n", errno, (char*)sFileName.c_str()); return -1; } fsize = (curl_off_t)file_info.st_size; pFile = fopen((char*)sFileName.c_str(), "rb"); //打开文件,返回结果用文件存储 if (NULL == pFile) { EPRINT("uploadFileContent open file error(%d), %s\n", errno, (char*)sFileName.c_str()); return -1; //打开文件失败 } //设定传输方式 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POST, 1); //CURL公共操作方式 nCode = messagePublicMethod(nFormat); if(0 != nCode) { if(NULL != pFile) { fclose(pFile); pFile = NULL; } EPRINT("uploadFileContent call messagePublicMethod error(%d) \n", errno); return -1; } // 设置回调函数 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_READFUNCTION, httpReadFile); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_READDATA, pFile); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_POSTFIELDSIZE, (curl_off_t)fsize); sRec = ""; //清空数据 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, (void*)&amp;sRec); res = curl_easy_perform(this-&gt;m_pCurl); //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } //关闭文件 fclose(pFile); pFile = NULL; return nCode;</code></pre> <p>} catch(...) { if(NULL != pFile) { fclose(pFile); pFile = NULL; } EPRINT(&quot;uploadFileContent api exception(%d)\n&quot;, errno); return -1; //接口异常 }</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>宏定义上传文件相关信息 */ <h1>define FILE_NAME_MAX_SIZE (128)</h1></li> </ul> <p>/*</p> <ul> <li>从文件全路径中获取文件名指针</li> <li> <p>返回文件名地址 <em>/ const char</em> ClusterCurl::getFileName(const char *path) { if(!path) { return NULL; }</p> <p>//找最后一个斜杠/ const char *pname = strrchr(path, '/'); if(!pname) { //没找到斜杠,则认为path就是文件名 return path; }</p> <p>//找到最后一个斜杠, 反回指针加1 return (char*)(pname + 1); }</p> </li> </ul> <p>/*</p> <ul> <li>上传文件</li> <li>参数1:文件名</li> <li>参数2:返回数据</li> <li> <p>返回值int, 0表示成功, 1表示超时,其他表示失败 <em>/ int ClusterCurl::uploadFile(const std::string&amp; sFileFullname, std::string&amp; sRec) { CURLcode res = CURLE_OK; int nCode = 0; struct curl_httppost </em>formpost = NULL; struct curl_httppost <em>lastptr = NULL; struct curl_slist </em>headerlist = NULL; static const char buf[] = &quot;Expect:&quot;;</p> <p>try { if(sFileFullname.empty()) { EPRINT(&quot;uploadFile sFileFullname is empty\n&quot;); return -1; //文件名为空 }</p> <pre><code>//获取文件名 const char* pFileName = getFileName(sFileFullname.c_str()); if(NULL == pFileName || '\0' == pFileName[0]) { EPRINT("uploadFileContent call getFileName failure, sFileFullname=%s \n", sFileFullname.c_str()); return -1; } DPRINT("uploadFile pFileName=%s \n", pFileName); //CURL公共操作方式 nCode = messagePublicMethod(FORMAT_DEFAULT); if(0 != nCode) { EPRINT("uploadFile call messagePublicMethod error(%d) \n", errno); return -1; } /* Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called. */ curl_formadd(&amp;formpost, &amp;lastptr, CURLFORM_COPYNAME, "sendfile", CURLFORM_FILE, sFileFullname.c_str(), CURLFORM_END); /* Fill in the filename field */ curl_formadd(&amp;formpost, &amp;lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_COPYCONTENTS, pFileName, CURLFORM_END); /* Fill in the submit field too, even if this is rarely needed */ curl_formadd(&amp;formpost, &amp;lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); headerlist = curl_slist_append(headerlist, buf); /* only disable 100-continue header if explicitly requested */ curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_HTTPPOST, formpost); //返回值 sRec = ""; //清空数据 curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter); curl_easy_setopt(this-&gt;m_pCurl, CURLOPT_WRITEDATA, (void*)&amp;sRec); /* Perform the request, res will get the return code */ res = curl_easy_perform(this-&gt;m_pCurl); /* then cleanup the formpost chain */ if(NULL != formpost) { curl_formfree(formpost); formpost = NULL; } /* free slist */ if( NULL != headerlist) { curl_slist_free_all (headerlist); headerlist = NULL; } //处理curl返回值 nCode = dealResCode(res); if(0 &gt; nCode) { EPRINT("deal response code error \n"); } return nCode;</code></pre> <p>} catch(...) { if(NULL != formpost) { curl_formfree(formpost); formpost = NULL; }</p> <pre><code>if( NULL != headerlist) { curl_slist_free_all (headerlist); headerlist = NULL; } EPRINT("uploadFile api exception(%d)\n", errno); return -1; //接口异常</code></pre> <p>}</p> </li> </ul> <p>}</p> <pre><code>**demo.cpp** </code></pre> <h1>include <stdio.h></h1> <h1>include <string></h1> <h1>include<iostream></h1> <h1>include &quot;sign.h&quot;</h1> <h1>include <cstdlib></h1> <h1>include <ctime></h1> <h1>include <sstream></h1> <h1>include &quot;manager_curl.h&quot;</h1> <p>//for test</p> <h1>define EPRINT printf</h1> <h1>define DPRINT printf</h1> <p>//应用的秘钥信息 std::string g_app_key = &quot;xxxxx&quot;; std::string g_app_Secrect = &quot;xxxxx&quot;;</p> <p>int str2num(string s) { int num; stringstream ss(s); ss &gt;&gt; num; return num; }</p> <p>string num2str(int i) { stringstream ss; ss &lt;&lt; i; return ss.str(); }</p> <p>/*</p> <ul> <li>通过get 、delete方式发送数据</li> <li> <p>返回值int, 0表示成功,1表示超时, 其它表示失败 */ int curl_get_message() { int nCode = -1;</p> <p>std::string sIP = &quot;pub-gw.uu.cc&quot;; unsigned int nPort = 80; std::string sUser = &quot;&quot;; //可为空 std::string sPwd = &quot;&quot;; //可为空 </p> <p>//这边用智能指针更好 ClusterCurl* pCluster_Curl = new ClusterCurl(sIP, nPort, sUser, sPwd); if(NULL == pCluster_Curl) { //创建Curl对象失败 EPRINT(&quot;new object failure!!!!!\n&quot;); return -1; }</p> <p>//curl初始化 nCode = pCluster_Curl-&gt;initCurlResource(); if(0 != nCode) { EPRINT(&quot;curl init failure!!!!!\n&quot;); delete pCluster_Curl; pCluster_Curl = NULL; return -1; }</p> <p>//设置路径 std::string sUrlPath = &quot;/public-gateway/xxxx?param=xxxx&quot;; pCluster_Curl-&gt;setUrlPath(sUrlPath);</p> <p>//发送方式为get,数据格式为默认,内容为空 int nMethod = METHOD_GET; int nFormat = FORMAT_JSON; std::string sMsg; std::string sRec;</p> <p>srand((int)time(0)); // 产生随机种子 std::map&lt;std::string,std::string&gt; mParam;</p> <p>std::string strNonce = num2str(rand()); std::string strTimestamp =num2str((int)time(0));</p> <p>//参与签名的参数,这些字段必须有 //注意map的key默认为字典升级排序,用其他技术要注意key排序 mParam.insert(make_pair(&quot;AppKey&quot;,g_app_key)); mParam.insert(make_pair(&quot;Nonce&quot;,strNonce)); //随机数,防止重放 mParam.insert(make_pair(&quot;Timestamp&quot;,strTimestamp)); //请求时间戳 mParam.insert(make_pair(&quot;param&quot;,&quot;xxxx&quot;)); //get参数</p> <p>string Signature; sign mysin(g_app_key,g_app_Secrect);</p> <p>if(mysin.generateSignature(mParam,Signature)) { //设置公共请求头 //User-Agent 固定这些值 pCluster_Curl-&gt;setHeaders(&quot;User-Agent:platform:CP;channel:CP;appVersion:1.0.0;package:com.cp.sdk;sdkVersion:1.0.0;sdkName:MSSDK;networkType:WiFi;deviceBrand:common;deviceId:00000000;localTime:2019-01-01 00:00:00&quot;); pCluster_Curl-&gt;setHeaders(&quot;Accept-Language:zh_CN&quot;); pCluster_Curl-&gt;setHeaders(&quot;AppKey:&quot; + mParam[&quot;AppKey&quot;]); pCluster_Curl-&gt;setHeaders(&quot;Nonce:&quot;+mParam[&quot;Nonce&quot;]); pCluster_Curl-&gt;setHeaders(&quot;Signature:&quot;+Signature); pCluster_Curl-&gt;setHeaders(&quot;Timestamp:&quot;+mParam[&quot;Timestamp&quot;]); //pCluster_Curl-&gt;setHeaders(&quot;Content-Type: application/json;charset=UTF-8&quot;);//注意这里不需要设置,在sendMsg函数有设置 } else { std::cout &lt;&lt; &quot;Signature failed !&quot; &lt;&lt; std::endl; delete pCluster_Curl; pCluster_Curl = NULL; return -1; }</p> <p>nCode = pCluster_Curl-&gt;sendMsg(sMsg, nMethod, nFormat,sRec);</p> <p>std::cout &lt;&lt; &quot;code:&quot; &lt;&lt; nCode&lt;&lt;std::endl; std::cout &lt;&lt; &quot;response:&quot; &lt;&lt; sRec &lt;&lt; std::endl;</p> <p>delete pCluster_Curl;</p> <p>return nCode;</p> </li> </ul> <p>}</p> <p>/*</p> <ul> <li>通过post 、put方式发送数据</li> <li> <p>返回值int, 0表示成功,1表示超时, 其它表示失败 */ int curl_post_message() { int nCode = -1; std::string sIP = &quot;pub-gw.uu.cc&quot;; unsigned int nPort = 80; std::string sUser = &quot;&quot;; //可为空 std::string sPwd = &quot;&quot;; //可为空 </p> <p>ClusterCurl* pCluster_Curl = new ClusterCurl(sIP, nPort, sUser, sPwd); if(NULL == pCluster_Curl) { //创建Curl对象失败 printf(&quot;new object failure!!!!!\n&quot;); return -1; }</p> <p>//curl初始化 nCode = pCluster_Curl-&gt;initCurlResource(); if(0 != nCode) { EPRINT(&quot;curl init failure!!!!!\n&quot;); delete pCluster_Curl; pCluster_Curl = NULL; return -1; }</p> <p>//设置路径 std::string sUrlPath = &quot;/public-gateway/xxx/xxxx/checkSession&quot;; pCluster_Curl-&gt;setUrlPath(sUrlPath);</p> <p>//发送方式为post,数据格式为json,发送数据为json int nMethod = METHOD_POST; int nFormat = FORMAT_JSON; std::string sRec; //自己构造json字符串 std::string sMsg = &quot;{&quot;; sMsg += &quot;\&quot;sessionId\&quot;:\&quot;c0a2296d9195572df7275f297b0ef525\&quot;,&quot;; sMsg += &quot;\&quot;openId\&quot;:\&quot;a1eedfe67d69234a663e93aa5035ee7aa2628a8278ba0cb2da0a4438db2a14ec\&quot;,&quot;; sMsg += &quot;\&quot;appkey\&quot;:&quot;; sMsg += &quot;\&quot;&quot;; sMsg += g_app_key; sMsg += &quot;\&quot;&quot;; sMsg += &quot;}&quot;;</p> <p>srand((int)time(0)); // 产生随机种子 std::map&lt;std::string,std::string&gt; mParam;</p> <p>std::string strNonce = num2str(rand()); std::string strTimestamp =num2str((int)time(0));</p> <p>//参与签名的参数,这些字段必须有 //注意map的key默认为字典升级排序,用其他技术要注意key排序 mParam.insert(make_pair(&quot;AppKey&quot;,g_app_key)); mParam.insert(make_pair(&quot;Nonce&quot;,strNonce)); //随机数,防止重放 mParam.insert(make_pair(&quot;Timestamp&quot;,strTimestamp)); //请求时间戳 mParam.insert(make_pair(&quot;requestBody&quot;,sMsg)); //post数据内容</p> <p>string Signature; sign mysin(g_app_key,g_app_Secrect);</p> <p>if(mysin.generateSignature(mParam,Signature)) { //设置公共请求头 pCluster_Curl-&gt;setHeaders(&quot;User-Agent:platform:CP;channel:CP;appVersion:1.0.0;package:com.cp.sdk;sdkVersion:1.0.0;sdkName:MSSDK;networkType:WiFi;deviceBrand:common;deviceId:00000000;localTime:2019-01-01 00:00:00&quot;); pCluster_Curl-&gt;setHeaders(&quot;Accept-Language:zh_CN&quot;); pCluster_Curl-&gt;setHeaders(&quot;AppKey:&quot; + mParam[&quot;AppKey&quot;]); pCluster_Curl-&gt;setHeaders(&quot;Nonce:&quot;+mParam[&quot;Nonce&quot;]); pCluster_Curl-&gt;setHeaders(&quot;Signature:&quot;+Signature); pCluster_Curl-&gt;setHeaders(&quot;Timestamp:&quot;+mParam[&quot;Timestamp&quot;]); //pCluster_Curl-&gt;setHeaders(&quot;Content-Type: application/json;charset=UTF-8&quot;);//注意这里不需要设置,在sendMsg函数有设置 } else { std::cout &lt;&lt; &quot;Signature failed !&quot; &lt;&lt; std::endl; delete pCluster_Curl; pCluster_Curl = NULL; return -1; }</p> <p>//发送数据,nFormat设置为FORMAT_JSON nCode = pCluster_Curl-&gt;sendMsg(sMsg, nMethod, nFormat,sRec);</p> <p>std::cout &lt;&lt; &quot;code:&quot; &lt;&lt; nCode&lt;&lt;std::endl; std::cout &lt;&lt; &quot;response:&quot; &lt;&lt; sRec &lt;&lt; std::endl;</p> <p>delete pCluster_Curl;</p> <p>return nCode;</p> </li> </ul> <p>}</p> <p>int main() { //全局资源初始化,放在主线程 ClusterCurl::globalInit();</p> <pre><code>//发送数据操作 curl_get_message(); //curl_post_message(); //全局资源清除,放在主线程中 ClusterCurl::globalCleanup(); return 0; </code></pre> <p>}</p> <pre><code>** makefile** </code></pre> <h1>Get the ROOT_PATH which common files located, assuming this makefile located in $(ROOT_PATH)/src/sub_module</h1> <p>ROOT_PATH := $(shell pwd)</p> <h1>Set target output path and the path of intermidiate object</h1> <h1>The path macros should include in $(ROOT_PATH)/path</h1> <p>OUT_PATH = $(ROOT_PATH)/bin OBJ_PATH = $(ROOT_PATH)/obj TARGET = $(OUT_PATH)/demo</p> <h1>Custom Predefines</h1> <h1>CFLAGS += -DXXXXXXXX</h1> <h1>Dependent header files</h1> <h1>The path macros should include in $(ROOT_PATH)/path</h1> <p>CFLAGS += -I./src</p> <h1>Dependent libraries</h1> <h1>The path macros should include in $(ROOT_PATH)/path</h1> <p>CURL_LIB_PATH= /usr/local/lib LDFLAGS += -L$(CURL_LIB_PATH) -lcurl</p> <h1>Set CPP source directory</h1> <p>CPP_SRCDIR = ./src</p> <h1>Or set specific CPP Source files</h1> <p>ADDITIONAL_CPP_SOURCES =</p> <h1>Traverse every directory in $(CPP_SRCDIR), and find every cpp file</h1> <p>CPP_SOURCES = $(foreach d,$(CPP_SRCDIR),$(wildcard $(d)/*.cpp) ) $(ADDITIONAL_CPP_SOURCES)</p> <h1>Traverse every cpp file in $(CPP_SOURCES) and get corresponding object file(.o)</h1> <p>CPP_OBJFILES = $(patsubst %.cpp,$(OBJ_PATH)/%.o,$(notdir $(CPP_SOURCES)))</p> <h1>Set C source directory</h1> <p>C_SRCDIR =./src</p> <h1>Or set specific C Source files</h1> <p>ADDITIONAL_C_SOURCES =</p> <h1>C Source files</h1> <p>C_SOURCES = $(foreach d,$(C_SRCDIR),$(wildcard $(d)/*.c) ) $(ADDITIONAL_C_SOURCES) C_OBJFILES = $(patsubst %.c,$(OBJ_PATH)/%.o,$(notdir $(C_SOURCES)))</p> <h1>Set vpath where to find these types of files</h1> <p>vpath %.cpp $(dir $(CPP_SOURCES)) vpath %.c $(dir $(C_SOURCES)) vpath %.o $(OBJ_PATH)</p> <h1>The first target to be executed</h1> <p>all: target</p> <p>target: $(TARGET)</p> <h1>Static dependecy pattern</h1> <h1>$(OBJ_PATH)/%.o define the pattern of target and %.c or %.cpp is the final dependency</h1> <p>$(C_OBJFILES): $(OBJ_PATH)/%.o : %.c -mkdir -p $(OBJ_PATH) $(CXX) -c $(CFLAGS) -o $@ $&lt;</p> <p>$(CPP_OBJFILES): $(OBJ_PATH)/%.o : %.cpp -mkdir -p $(OBJ_PATH) $(CXX) -c $(CFLAGS) -o $@ $&lt;</p> <p>$(TARGET): $(CPP_OBJFILES) $(C_OBJFILES) -mkdir -p $(OUT_PATH) $(CXX) -o $@ $^ $(LDFLAGS)</p> <p>clean: -rm -rf $(OBJ_PATH) -rm -f $(TARGET)</p> <pre><code> **注意** g_app_key,g_app_Secrect替换成自己的,sUrlPath填写要访问url地址,程序依赖libcurl库,安装libcurl修改makefile中LDFLAGS的路径</code></pre>

页面列表

ITEM_HTML