签名示例
<p>[TOC]</p>
<h3>PHP版本外部网关调用demo</h3>
<pre><code class="language-php"><?php
//业务控制台拉取的配置
$appkey = 'xxx'; //appkey
$appSecret = 'xxxx';//appsecret
//顺序不能变
//详情请看:https://www.showdoc.cc/mssdk?page_id=3123995334349155
$userAgent = array
(
'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'
);
//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))->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))->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->appKey = $appKey;
$this->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->buildSignHeaders($authorization);
$signStr = $this->buildSignStr($requestMethod, $signHeaderData, $requestData);
$signature = $this->sign($signStr);
$curlHeadersArray = $this->buildCurlHeaders($signature, $signHeaderData, $userAgent);
// echo $signStr;die;
$response = $this->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 => $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&%s&%s';
$signStr = sprintf($signStrFormat, $this->appSecret, $signStr, $this->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' => $requestJsonStr];
$data = array_merge($signHeaderData, $postData);
} else {
//合并请求参数和请求头
$data = array_merge($signHeaderData, $requestData);
}
// print_r($data);die;
//字典排序
ksort($data);
// 拼成url请求参数Key1=value1& Key2=value2& Key3=value3&…………
$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" => $this->appKey,
"Nonce" => $nonce,
"Timestamp" => $timeStamp,
];
if(!is_null($authorization) && strlen(trim($authorization))>1){
$signHeaders['Authorization'] = $authorization;
}
return $signHeaders;
}
}
</code></pre>
<h3>PHP版本内部网关调用demo</h3>
<pre><code class="language-php"><?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))->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))->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->appKey = $appKey;
$this->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->buildSignHeaders();
$signStr = $this->buildSignStr($requestMethod, $signHeaderData, $requestData);
$signature = $this->sign($signStr);
$curlHeadersArray = $this->buildCurlHeaders($signature, $signHeaderData);
// echo $signStr;die;
$response = $this->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&%s&%s';
$signStr = sprintf($signStrFormat, $this->appSecret, $signStr, $this->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' => $requestJsonStr];
$data = array_merge($signHeaderData, $postData);
} else {
//合并请求参数和请求头
$data = array_merge($signHeaderData, $requestData);
}
// print_r($data);die;
//字典排序
ksort($data);
// 拼成url请求参数Key1=value1& Key2=value2& Key3=value3&…………
$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" => $this->appKey,
"Nonce" => $nonce,
"Timestamp" => $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<String, String> params) {
StringBuffer content = new StringBuffer();
// 按照key做排序
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
boolean isFirst = true;
for (int i = 0; i < 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 && value.length() >0) {
content.append((isFirst ? "" : "&") + key + "=" + value);
isFirst = false;
}
}
return content.toString();
}
/**
* 将Map中的数据组装成url
* @param params
* @return
* @throws UnsupportedEncodingException
*/
public static String mapToUrl(Map<String, String> 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("&" + key + "=" + URLEncoder.encode(value, "utf-8"));
} else {
sb.append("&" + key + "=");
}
}
}
return sb.toString();
}
/**
* 取得URL中的参数值。
* <p>如不存在,返回空值。</p>
*
* @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 < 0) {
return null;
}
start += name.length();
int end = url.indexOf("&", 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 + "&" + (content == null ? "" : content) + "&" + 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<iostream>
#include<string>
#include<map>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
class sign{
public:
sign(const string appKey,const string appSecrect);
~sign();
bool generateSignature(map<string,string> mParam,string &signature);
bool checkSignature(map<string,string> mParam,const string &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 "sign.h"</h1>
<h1>include<algorithm></h1>
<h1>include<openssl/md5.h></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<string,string> mParam,string &signature)
{
if(mParam.empty() || m_strAppSecrect.empty()){
return false;
}</p>
<pre><code>string content=m_strAppSecrect;
map<string,string>::iterator iter;
for(iter=mParam.begin();iter !=mParam.end();++iter){
//排查签名字段
if(iter->first == "Signature"){
continue;
}
content.append("&");
content.append(iter->first);
content.append("=");
content.append(iter->second);
}
content.append("&");
content.append(m_strAppSecrect);
signature= md5(content);
cout<<"content:" << content << endl;
cout << "signature:" << signature << 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(&ctx); //初始化一个MD5_CTX这样的结构体
MD5_Update(&ctx,data.c_str(),strlen(data.c_str())); //更新这块区域,防止引用非法数据
MD5_Final(md,&ctx); //最后把ctx中的数据按照MD5算法生成16位的MD5码,存放到md中
string md5Value;
for( i=0; i<sizeof(md); i++ ){
sprintf(tmp,"%02X",md[i]);
md5Value.append(tmp);
}
return md5Value;</code></pre>
<p>}</p>
<p>bool sign::checkSignature(map<string,string> mParam,const string &signature)
{
string strSign;
if(generateSignature(mParam,strSign)){
cout<<"strSign:" << strSign << "signature:" << signature << 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 <curl/curl.h></h1>
<h1>include <string></h1>
<h1>include "manager_lock.h"</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& sIP,
const unsigned int nPort,
const std::string& sUser,
const std::string& sPwd);
~ClusterCurl();
// 设置等待连接最长时间
void setConnectTimeout(unsigned int nTime);
// 设置传输最长时间
void setTimeout(unsigned int nTime);
//设置服务器参数
void setServer(const std::string& sIP,
const unsigned int nPort,
const std::string& sUser,
const std::string& sPwd);
//设置URL路径
void setUrlPath(const std::string& sUrlPath);
//设置请求头
void setHeaders(const std::string &sHeader);
//发送消息发送方式
int sendMsg(const std::string& sMsg,
const int nMethod,
const int nFormat,
std::string& sRec);
//下载文件
int downloadFile(const std::string& sFileName, const int nFormat);
//从文件中读取内容post出去
int uploadFileContent(const std::string& sFileName, const int nFormat, std::string& sRec);
//上传文件
int uploadFile(const std::string& sFileFullname, std::string& 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& sMsg, const int nFormat, std::string& sRec);
//通过post的方式发送信息
int postMsg(const std::string& sMsg, const int nFormat, std::string& sRec);
//通过put的方式发送信息
int putMsg(const std::string& sMsg, const int nFormat, std::string& sRec);
//通过delete进行操作
int deleteMsg(const std::string& sMsg, const int nFormat, std::string& 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 <sys/stat.h></h1>
<h1>include <errno.h></h1>
<h1>include "manager_curl.h"</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& sIP,
const unsigned int nPort,
const std::string& sUser,
const std::string& 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->m_pHeaders)
{
curl_slist_free_all(this->m_pHeaders);
this->m_pHeaders = NULL;
}</p>
<pre><code>if(NULL != this->m_pCurl)
{
releaseCurlResource();
}</code></pre>
<p>}
catch(...) //吞下异常,防止异常逃离析构函数
{
EPRINT("~ClusterCurl api exception error(%d) \n", 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("globalInit mutex lock error(%d)\n", 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 && 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("globalCleanup mutex lock error(%d)\n", 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 && 0 != nUnlockJudge)
{
ClusterCurl::s_MutexLock.unlock();
}
EPRINT("globalCleanup api exception(%d)\n", errno);
return -1; //异常接口
}</p>
</li>
</ul>
<p>}</p>
<p>/*</p>
<ul>
<li>进行单个线程CURL简单资源进行初始化</li>
<li>返回值int, 0表示成功, 其它表示失败
*/
int ClusterCurl::initCurlResource()
{
this->m_pCurl = curl_easy_init();
if(NULL == this->m_pCurl)
{
EPRINT("curl easy init failure \n");
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->m_pCurl)
{
EPRINT("releaseCurlResource curl ptr is null \n");
return -1; //CURL指针为NULL
}</p>
<p>//释放curl指针
curl_easy_cleanup(this->m_pCurl);
this->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->m_pCurl)
{
EPRINT("setUserPwd curl ptr is null \n");
return -1; //CURL指针为NULL
}</p>
<p>std::string sUserPwd;
if((!(this->m_sUser.empty())) && (!(this->m_sPwd.empty())))
{
sUserPwd = this->m_sUser + ":" + this->m_sPwd;
curl_easy_setopt(this->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->m_contect_timeout = nTime;
}</li>
</ul>
<p>/*</p>
<ul>
<li>设置传输最长时间</li>
<li>参数1:最长时间秒数
*/
void ClusterCurl::setTimeout(unsigned int nTime)
{
this->m_timeout = nTime;
}</li>
</ul>
<p>//设置请求头
void ClusterCurl::setHeaders(const std::string &sHeader)
{
if(NULL == this->m_pCurl)
{
EPRINT("setDataFormat curl ptr is null \n");
return; //CURL指针为NULL
}</p>
<pre><code> //非空设置相应格式,空则不设置
if(NULL == this->m_pHeaders){
this->m_pHeaders = curl_slist_append(NULL, (char*)sHeader.c_str());
}
else{
this->m_pHeaders = curl_slist_append(this->m_pHeaders, (char*)sHeader.c_str());
}
if(NULL == this->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 "Content-Type: application/xml;charset=UTF-8"</h1>
<p>//JSON格式</p>
<h1>define JSON_FORMAT_STRING "Content-Type: application/json;charset=UTF-8"</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->m_pCurl)
{
EPRINT("setDataFormat curl ptr is null \n");
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->m_pHeaders){
this->m_pHeaders = curl_slist_append(NULL, (char<em>)sFormatStr.c_str());
}
else {
this->m_pHeaders = curl_slist_append(this->m_pHeaders, (char</em>)sFormatStr.c_str());
}</p>
<pre><code>if(NULL == this->m_pHeaders)
{
EPRINT("setDataFormat set format error(%d) \n", errno);
return -1;
}
curl_easy_setopt(this->m_pCurl, CURLOPT_HTTPHEADER, this->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& sIP,
const unsigned int nPort,
const std::string& sUser,
const std::string& sPwd)
{
this->m_sIP = sIP;
this->m_nPort = nPort;
this->m_sUser = sUser;
this->m_sPwd = sPwd;
}</li>
</ul>
<p>/*</p>
<ul>
<li>设置URL路径</li>
<li>参数1:URL路径
*/
void ClusterCurl::setUrlPath(const std::string& sUrlPath)
{
this->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->append((char <em>)buffer, ((char</em>)buffer)+totalSize);
return totalSize;
}
else
{
EPRINT("ClusterCurl httpDataWriter data error(%d) \n", 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& sMsg,
const int nMethod,
const int nFormat,
std::string& sRec)
{
int nCode = -1;
sRec = ""; //清空数据
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("sendMsg method error\n");
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->m_pCurl)
{
EPRINT("messagePublicMethod curl ptr is null\n");
return -1; //CURL指针为NULL
}</p>
<pre><code>//参数合法性检测
if(0 > nFormat)
{
EPRINT("messagePublicMethod params error, nFormat=%d \n", nFormat);
return -1; //CURL指针为NULL
}
//指定url
if(this->m_sIP.empty())
{
EPRINT("messagePublicMethod ip is empty\n");
return -1;
}
std::string sUrl;
sUrl = sUrl + "http://" + this->m_sIP + this->m_sUrlPath;
DPRINT("sUrl: %s\n", sUrl.c_str());
curl_easy_setopt(this->m_pCurl, CURLOPT_URL, (char*)sUrl.c_str());
curl_easy_setopt(this->m_pCurl, CURLOPT_PORT, this->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->m_pCurl, CURLOPT_NOSIGNAL, 1);
//设置超时时间
if(0 >= this->m_contect_timeout)
{
this->m_contect_timeout = CONNECT_DEFAULT_TIMEOUT;
}
curl_easy_setopt(this->m_pCurl, CURLOPT_CONNECTTIMEOUT, this->m_contect_timeout);
if(0 >= this->m_timeout)
{
this->m_timeout = DEFAULT_TIMEOUT;
}
curl_easy_setopt(this->m_pCurl, CURLOPT_TIMEOUT, this->m_timeout);
/*
第一:默认情况下libcurl完成一个任务以后,出于重用连接的考虑不会马上关闭,如果每次目标主机不一样,这里禁止重连接
第二:每次执行完curl_easy_perform,licurl会继续保持与服务器的连接。接下来的请求可以使用这个连接而不必创建新的连接,如果目标主机是同一个的话。
这样可以减少网络开销。
*/
curl_easy_setopt(this->m_pCurl, CURLOPT_FORBID_REUSE, 1);
return 0;</code></pre>
<p>}
catch(...)
{
EPRINT("messagePublicMethod api exception(%d)\n", 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("%s\n",pRes);</p>
<p>//http返回码
long lResCode = 0;
curl_easy_getinfo(this->m_pCurl, CURLINFO_RESPONSE_CODE, &lResCode);</p>
<p>if(CURLE_OK != res || 200 != lResCode)
{
//curl传送失败
if(CURLE_OPERATION_TIMEOUTED == res)
{
nCode = 1; //超时返回1
}
else
{
nCode = -1; //其它错误返回-1
}
EPRINT("curl send msg error: pRes=%s, lResCode=%ld \n", 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& sMsg, const int nFormat, std::string& sRec)
{
CURLcode res = CURLE_OK;
int nCode = -1;</p>
<p>try
{
if(NULL == this->m_pCurl)
{
EPRINT("putMsg curl ptr is null\n");
return -1; //CURL指针为NULL
}</p>
<pre><code>//发送数据,以及发送方式
curl_easy_setopt(this->m_pCurl, CURLOPT_CUSTOMREQUEST, "PUT");
if(sMsg.empty())
{
curl_easy_setopt(this->m_pCurl, CURLOPT_POSTFIELDS, "");
}
else
{
curl_easy_setopt(this->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->m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, (void*)&sRec);
res = curl_easy_perform(this->m_pCurl);
//处理curl返回值
nCode = dealResCode(res);
if(0 > nCode)
{
EPRINT("deal response code error \n");
}
return nCode;</code></pre>
<p>}
catch(...)
{
EPRINT("putMsg api exception(%d)\n", 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& sMsg, const int nFormat, std::string& sRec)
{
CURLcode res = CURLE_OK;
int nCode = -1;</p>
<p>try
{
if(NULL == this->m_pCurl)
{
EPRINT("deleteMsg curl ptr is null\n");
return -1; //CURL指针为NULL
}</p>
<pre><code>//发送数据,以及发送方式
curl_easy_setopt(this->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->m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, (void*)&sRec);
res = curl_easy_perform(this->m_pCurl);
//处理curl返回值
nCode = dealResCode(res);
if(0 > nCode)
{
EPRINT("deal response code error \n");
}
return nCode;</code></pre>
<p>}
catch(...)
{
EPRINT("deleteMsg api exception(%d)\n", 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& sMsg, const int nFormat, std::string& sRec)
{
CURLcode res = CURLE_OK;
int nCode = -1;</p>
<p>try
{
if(NULL == this->m_pCurl)
{
EPRINT("postMsg curl ptr is null\n");
return -1; //CURL指针为NULL
}</p>
<pre><code>//发送数据,以及发送方式
curl_easy_setopt(this->m_pCurl, CURLOPT_POST, 1);
if(sMsg.empty())
{
curl_easy_setopt(this->m_pCurl, CURLOPT_POSTFIELDS, "");
}
else
{
curl_easy_setopt(this->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->m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, (void*)&sRec);
res = curl_easy_perform(this->m_pCurl);
//处理curl返回值
nCode = dealResCode(res);
if(0 > nCode)
{
EPRINT("deal response code error \n");
}
return nCode;</code></pre>
<p>}
catch(...)
{
EPRINT("postMsg api exception(%d)\n", 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& sMsg, const int nFormat, std::string& sRec)
{
CURLcode res = CURLE_OK;
int nCode = -1;</p>
<p>try
{
if(NULL == this->m_pCurl)
{
EPRINT("getMsg curl ptr is null\n");
return -1; //CURL指针为NULL
}</p>
<pre><code>//设定传输方式
curl_easy_setopt(this->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->m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, (void*)&sRec);
res = curl_easy_perform(this->m_pCurl);
//处理curl返回值
nCode = dealResCode(res);
if(0 > nCode)
{
EPRINT("deal response code error \n");
}
return nCode;</code></pre>
<p>}
catch(...)
{
EPRINT("getMsg api exception(%d)\n", 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& sFileName, const int nFormat)
{
CURLcode res = CURLE_OK;
FILE</em> pFile = NULL;
int nCode = -1;</p>
<p>try
{
if(sFileName.empty())
{
EPRINT("downloadFile filename is empty\n");
return -1; //文件名为空
}
pFile = fopen((char<em>)sFileName.c_str(), "w"); //打开文件,返回结果用文件存储
if (NULL == pFile)
{
EPRINT("downloadFile open file error(%d), %s\n", errno, (char</em>)sFileName.c_str());
return -1; //打开文件失败
}</p>
<pre><code>//设定传输方式
curl_easy_setopt(this->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->m_pCurl, CURLOPT_WRITEFUNCTION, httpWriteFile);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, pFile);
res = curl_easy_perform(this->m_pCurl);
//处理curl返回值
nCode = dealResCode(res);
if(0 > 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("downloadFile api exception(%d)\n", 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& sFileName, const int nFormat, std::string& 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("uploadFileContent filename is empty\n");
return -1; //文件名为空
}</p>
<pre><code>if(stat((char*)sFileName.c_str(), &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->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->m_pCurl, CURLOPT_READFUNCTION, httpReadFile);
curl_easy_setopt(this->m_pCurl, CURLOPT_READDATA, pFile);
curl_easy_setopt(this->m_pCurl, CURLOPT_POSTFIELDSIZE, (curl_off_t)fsize);
sRec = ""; //清空数据
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, (void*)&sRec);
res = curl_easy_perform(this->m_pCurl);
//处理curl返回值
nCode = dealResCode(res);
if(0 > 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("uploadFileContent api exception(%d)\n", 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& sFileFullname, std::string& 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[] = "Expect:";</p>
<p>try
{
if(sFileFullname.empty())
{
EPRINT("uploadFile sFileFullname is empty\n");
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(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, sFileFullname.c_str(),
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, pFileName,
CURLFORM_END);
/* Fill in the submit field too, even if this is rarely needed */
curl_formadd(&formpost,
&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->m_pCurl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(this->m_pCurl, CURLOPT_HTTPPOST, formpost);
//返回值
sRec = ""; //清空数据
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEFUNCTION, httpDataWriter);
curl_easy_setopt(this->m_pCurl, CURLOPT_WRITEDATA, (void*)&sRec);
/* Perform the request, res will get the return code */
res = curl_easy_perform(this->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 > 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 "sign.h"</h1>
<h1>include <cstdlib></h1>
<h1>include <ctime></h1>
<h1>include <sstream></h1>
<h1>include "manager_curl.h"</h1>
<p>//for test</p>
<h1>define EPRINT printf</h1>
<h1>define DPRINT printf</h1>
<p>//应用的秘钥信息
std::string g_app_key = "xxxxx";
std::string g_app_Secrect = "xxxxx";</p>
<p>int str2num(string s)
{
int num;
stringstream ss(s);
ss >> num;
return num;
}</p>
<p>string num2str(int i)
{
stringstream ss;
ss << 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 = "pub-gw.uu.cc";
unsigned int nPort = 80;
std::string sUser = ""; //可为空
std::string sPwd = ""; //可为空 </p>
<p>//这边用智能指针更好
ClusterCurl* pCluster_Curl = new ClusterCurl(sIP, nPort, sUser, sPwd);
if(NULL == pCluster_Curl)
{
//创建Curl对象失败
EPRINT("new object failure!!!!!\n");
return -1;
}</p>
<p>//curl初始化
nCode = pCluster_Curl->initCurlResource();
if(0 != nCode)
{
EPRINT("curl init failure!!!!!\n");
delete pCluster_Curl;
pCluster_Curl = NULL;
return -1;
}</p>
<p>//设置路径
std::string sUrlPath = "/public-gateway/xxxx?param=xxxx";
pCluster_Curl->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<std::string,std::string> mParam;</p>
<p>std::string strNonce = num2str(rand());
std::string strTimestamp =num2str((int)time(0));</p>
<p>//参与签名的参数,这些字段必须有
//注意map的key默认为字典升级排序,用其他技术要注意key排序
mParam.insert(make_pair("AppKey",g_app_key));
mParam.insert(make_pair("Nonce",strNonce)); //随机数,防止重放
mParam.insert(make_pair("Timestamp",strTimestamp)); //请求时间戳
mParam.insert(make_pair("param","xxxx")); //get参数</p>
<p>string Signature;
sign mysin(g_app_key,g_app_Secrect);</p>
<p>if(mysin.generateSignature(mParam,Signature))
{
//设置公共请求头
//User-Agent 固定这些值
pCluster_Curl->setHeaders("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");
pCluster_Curl->setHeaders("Accept-Language:zh_CN");
pCluster_Curl->setHeaders("AppKey:" + mParam["AppKey"]);
pCluster_Curl->setHeaders("Nonce:"+mParam["Nonce"]);
pCluster_Curl->setHeaders("Signature:"+Signature);
pCluster_Curl->setHeaders("Timestamp:"+mParam["Timestamp"]);
//pCluster_Curl->setHeaders("Content-Type: application/json;charset=UTF-8");//注意这里不需要设置,在sendMsg函数有设置
}
else
{
std::cout << "Signature failed !" << std::endl;
delete pCluster_Curl;
pCluster_Curl = NULL;
return -1;
}</p>
<p>nCode = pCluster_Curl->sendMsg(sMsg, nMethod, nFormat,sRec);</p>
<p>std::cout << "code:" << nCode<<std::endl;
std::cout << "response:" << sRec << 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 = "pub-gw.uu.cc";
unsigned int nPort = 80;
std::string sUser = ""; //可为空
std::string sPwd = ""; //可为空 </p>
<p>ClusterCurl* pCluster_Curl = new ClusterCurl(sIP, nPort, sUser, sPwd);
if(NULL == pCluster_Curl)
{
//创建Curl对象失败
printf("new object failure!!!!!\n");
return -1;
}</p>
<p>//curl初始化
nCode = pCluster_Curl->initCurlResource();
if(0 != nCode)
{
EPRINT("curl init failure!!!!!\n");
delete pCluster_Curl;
pCluster_Curl = NULL;
return -1;
}</p>
<p>//设置路径
std::string sUrlPath = "/public-gateway/xxx/xxxx/checkSession";
pCluster_Curl->setUrlPath(sUrlPath);</p>
<p>//发送方式为post,数据格式为json,发送数据为json
int nMethod = METHOD_POST;
int nFormat = FORMAT_JSON;
std::string sRec;
//自己构造json字符串
std::string sMsg = "{";
sMsg += "\"sessionId\":\"c0a2296d9195572df7275f297b0ef525\",";
sMsg += "\"openId\":\"a1eedfe67d69234a663e93aa5035ee7aa2628a8278ba0cb2da0a4438db2a14ec\",";
sMsg += "\"appkey\":";
sMsg += "\"";
sMsg += g_app_key;
sMsg += "\"";
sMsg += "}";</p>
<p>srand((int)time(0)); // 产生随机种子
std::map<std::string,std::string> mParam;</p>
<p>std::string strNonce = num2str(rand());
std::string strTimestamp =num2str((int)time(0));</p>
<p>//参与签名的参数,这些字段必须有
//注意map的key默认为字典升级排序,用其他技术要注意key排序
mParam.insert(make_pair("AppKey",g_app_key));
mParam.insert(make_pair("Nonce",strNonce)); //随机数,防止重放
mParam.insert(make_pair("Timestamp",strTimestamp)); //请求时间戳
mParam.insert(make_pair("requestBody",sMsg)); //post数据内容</p>
<p>string Signature;
sign mysin(g_app_key,g_app_Secrect);</p>
<p>if(mysin.generateSignature(mParam,Signature))
{
//设置公共请求头
pCluster_Curl->setHeaders("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");
pCluster_Curl->setHeaders("Accept-Language:zh_CN");
pCluster_Curl->setHeaders("AppKey:" + mParam["AppKey"]);
pCluster_Curl->setHeaders("Nonce:"+mParam["Nonce"]);
pCluster_Curl->setHeaders("Signature:"+Signature);
pCluster_Curl->setHeaders("Timestamp:"+mParam["Timestamp"]);
//pCluster_Curl->setHeaders("Content-Type: application/json;charset=UTF-8");//注意这里不需要设置,在sendMsg函数有设置
}
else
{
std::cout << "Signature failed !" << std::endl;
delete pCluster_Curl;
pCluster_Curl = NULL;
return -1;
}</p>
<p>//发送数据,nFormat设置为FORMAT_JSON
nCode = pCluster_Curl->sendMsg(sMsg, nMethod, nFormat,sRec);</p>
<p>std::cout << "code:" << nCode<<std::endl;
std::cout << "response:" << sRec << 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 $@ $<</p>
<p>$(CPP_OBJFILES): $(OBJ_PATH)/%.o : %.cpp
-mkdir -p $(OBJ_PATH)
$(CXX) -c $(CFLAGS) -o $@ $<</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>