c++利用jsoncpp libcurl 构造http 包(原)
我们手游要接入uc九游进行测试,要用http向uc那边的sdk 服务器post json数据。
虽然他们提供了php,java还有c#的服务端demo,但是我们服务器是C++写的,我实在不想中间再转一层。
于是查了一些资料,发现libcurl可以用在c++里用来构造http包,然后json可以用jsoncpp这个开源api来整合,于是就直接开干!
1.下载libcurl http://curl.haxx.se/download/curl-7.40.0.zip
2.下载jsoncpp https://github.com/open-source-parsers/jsoncpp
3.实现一个http线程,接收主线程推送过来的消息,并转化为json数据,并post到目标地址,在回调里获取到返回数据。
具体实现代码
HttpParse.h
#ifndef HttpParse_h__
#define HttpParse_h__ #include <curl/curl.h>
#include <string.h>
#include <string>
#include "ConfigHelper.hpp" #include "CodeQueue.hpp"
#include "Thread.hpp"
#include "TypesDefine.hpp"
#include "NowTime.hpp"
#include "StrStream.hpp" using namespace std;
using namespace KylinLib; struct stHttpData
{
enum actiontype
{
uc_login = , // 登陆
uc_recharge = , // 充值
uc_extend = , // 扩展数据
}; actiontype action; //动作id,登录?注册?
unsigned int uiUin; //QQ号
int iWorldid; //区id
int iLoginWay; //登录来源
int iChangeValue; //变化值
stHttpData()
{
memset(this,,sizeof(*this) );
}
}; class CHTTPParse
{
CCodeQueue* m_pDataQueue;
CURL* m_pCurlHandlder;
public:
//enum {appID = 90010006,};
enum {appID = ,};
CHTTPParse();
~CHTTPParse(); // 增加http数据
void AddOneHttpData(stHttpData::actiontype actType, unsigned int uiUin, int worldID, int changeValue = , int loginWay = ); // 发送数据
int ProcessMsgSend(); static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid); private:
// 初始化
void Init(); //Curl 初始化
void CurlInit(); //UC登录
int UCLogin(const char* szSid, const char* szAccount); //UC充值
int UCRecharge(unsigned int Roleid, int iWorldid, const char* szAccount, int iRechargeNum); //UC扩展数据
int UCSendExtend(); //发送数据
int SendHttpPost(const char* url,const char* pData);
}; //处理http交互的线程 class CHTTPParseThread : public CThread
{
int m_iIsToBeBlocked; public:
CHTTPParseThread();
public:
virtual int PrepareToRun()
{
return ;
}
virtual int Run() ; virtual int IsToBeBlocked()
{
return m_iIsToBeBlocked;
}
void SetBlockedStatus(int iStatus)
{
m_iIsToBeBlocked = iStatus;
}
}; #define CHTTPParseMgr CSingleton<CHTTPParse>::Instance() #endif // HttpParse_h__
// HttpParse.cpp
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <json/config.h>
#include <json/json.h> #include "HttpParse.hpp"
#include "LogAdapter.hpp" #define LUOPANGAPPID 100658092 #define DoSend(host, stat, data) \
CStrStream1024 strHttp; \
strHttp << "http://" \
<< host \
<< "/" \
<< stat; \
return SendHttpPost(strHttp.GetStr(), data); #define InitNet() CurlInit() CHTTPParseThread::CHTTPParseThread()
{
m_iIsToBeBlocked =;
} // 注册 登录 支付
int CHTTPParseThread::Run()
{ while(true)
{
if (m_iRunStatus == rt_stopped)
{
break;
} int iNewMsgCount = ; while(true)
{
int iRet = CHTTPParseMgr->ProcessMsgSend();
if (iRet ==)
{
iNewMsgCount++;
}
else
{
break;
}
} if (iNewMsgCount ==)
{
usleep(*); //1毫秒
} }
return ;
} CHTTPParse::CHTTPParse()
{
m_pDataQueue =NULL;
m_pCurlHandlder = NULL;
Init();
}
CHTTPParse::~CHTTPParse()
{
if (m_pCurlHandlder)
{
curl_easy_cleanup(m_pCurlHandlder);
}
curl_global_cleanup(); } // 增加上报数据
void CHTTPParse::AddOneHttpData(stHttpData::actiontype actType, unsigned int uiUin, int worldID, int changeValue /* = 0 */, int loginWay /* = 0 */)
{
if (NULL == m_pDataQueue)
{
return;
}
stHttpData lplData;
lplData.action = actType;
lplData.uiUin = uiUin;
lplData.iWorldid = worldID;
lplData.iChangeValue = changeValue;
lplData.iLoginWay = loginWay;
m_pDataQueue->PushOneCode( (const unsigned char*)&lplData,sizeof(lplData) );
} int CHTTPParse::ProcessMsgSend()
{
if (m_pDataQueue)
{
stHttpData stData;
int iCodelen;
m_pDataQueue->PopOneCode((unsigned char*)&stData,sizeof(stData),iCodelen); if ( iCodelen == sizeof(stData) )
{
switch (stData.action)
{
case stHttpData::uc_login: //登录
return UCLogin("test", "account1234");
break;
case stHttpData::uc_recharge: //注册
return UCRecharge(, , "account1234", );
break;
case stHttpData::uc_extend: //扩展
return UCSendExtend();
break;
}
}
else
{
return -;
}
}
return -;
} size_t CHTTPParse::OnWriteData( void* buffer, size_t size, size_t nmemb, void* lpVoid )
{
std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
if( NULL == str || NULL == buffer )
{
return -;
} char* pData = (char*)buffer;
str->append(pData, size * nmemb);
return nmemb;
} void CHTTPParse::Init()
{
//创建一个环形缓存队列来进行线程同步
m_pDataQueue = new CCodeQueue(*); //100K足够了吧
if (m_pDataQueue)
{
m_pDataQueue->Initialize();
} InitNet();
} void CHTTPParse::CurlInit()
{
curl_global_init(CURL_GLOBAL_ALL); m_pCurlHandlder = curl_easy_init();
if (m_pCurlHandlder == NULL)
{
TRACESVR( "Failed to create CURL connection\n");
return ;
}
return ; } int CHTTPParse::SendHttpPost(const char* url,const char* pData)
{
CURLcode code; TRACESVR_DEBUG("Http Data[%s]\n",pData);
if (NULL == m_pCurlHandlder)
{
return -;
}
code =curl_easy_setopt(m_pCurlHandlder, CURLOPT_NOSIGNAL, 1L);
if (code !=CURLE_OK)
{
TRACESVR("Failed to set URL [%d]\n", code);
return - ;
} //设置超时
curl_easy_setopt(m_pCurlHandlder, CURLOPT_TIMEOUT, );
//curl_easy_setopt(m_pCurlHandlder, CURLOPT_CONNECTTIMEOUT, 3); //设置method为post
//curl_easy_setopt(m_pCurlHandlder, CURLOPT_POST, 1);
curl_easy_setopt(m_pCurlHandlder, CURLOPT_VERBOSE, 1L);
curl_slist *http_headers = NULL;
http_headers = curl_slist_append(http_headers, "Accept: application/json");
http_headers = curl_slist_append(http_headers, "Content-Type: application/json");
http_headers = curl_slist_append(http_headers, "charsets: utf-8");
curl_easy_setopt(m_pCurlHandlder, CURLOPT_CUSTOMREQUEST, "POST");
code = curl_easy_setopt(m_pCurlHandlder, CURLOPT_HTTPHEADER, http_headers); code = curl_easy_setopt(m_pCurlHandlder, CURLOPT_URL, "http://192.168.1.166/sdkdemo/restful/dispatch.php?do=cp/account.verifySession");
if (code != CURLE_OK)
{
TRACESVR("Failed to set URL [%d]\n", code);
return - ;
}
code =curl_easy_setopt(m_pCurlHandlder, CURLOPT_POSTFIELDS, pData);
if (code != CURLE_OK)
{
TRACESVR("Failed to PostFields=%s, [code=%d]\n",pData, code);
return -;
}
code =curl_easy_setopt(m_pCurlHandlder, CURLOPT_WRITEFUNCTION, CHTTPParse::OnWriteData);
string strResp;
code =curl_easy_setopt(m_pCurlHandlder, CURLOPT_WRITEDATA, (void *)&strResp);
curl_easy_setopt(m_pCurlHandlder, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(m_pCurlHandlder, CURLOPT_SSL_VERIFYHOST, false);
curl_easy_setopt(m_pCurlHandlder,CURLOPT_FOLLOWLOCATION,); code = curl_easy_perform(m_pCurlHandlder);
if(CURLE_OK == code)
{
char *ct =NULL; code = curl_easy_getinfo(m_pCurlHandlder, CURLINFO_CONTENT_TYPE, &ct); if((CURLE_OK == code) && ct)
{
TRACESVR("We received Content-Type: %s \n", ct);
}
}
else
{
TRACESVR("curl_easy_perform Error\n");
}
curl_easy_cleanup(m_pCurlHandlder); return ;
} int CHTTPParse::UCLogin(const char* szSid, const char* szAccount)
{
Json::Value root;
// id
root["id"] = GETNOWTIMEUS; // service
root["service"] = "account.verifySession"; Json::Value gameid;
gameid["gameId"] = ;
root["game"] = gameid; Json::Value sid;
sid["sid"] = "eeeeettttttt555444";
root["data"] = sid; // encrypt
root["encrypt"] = "md5"; // sign
root["sign"] = "cce4cef6ea157f411932f9651555836e"; Json::FastWriter writer;
std::string strWrite = writer.write(root); DoSend("192.168.1.166", "sdkdemo/restful/dispatch.php?do=cp/account.verifySession", strWrite.c_str());
}
// 其他函数还没调试,就不贴出来了
注意事项
1.设置http post数据格式和accept格式
http_headers = curl_slist_append(http_headers, "Accept: application/json");
http_headers = curl_slist_append(http_headers, "Content-Type: application/json");
2.json数据如果有问题,会直接报 500 internal server erro 的错误,其实就是json的数据格式不对。最好填充完,用工具检测一下json字符串是否合法
3.jsoncpp中要用 Json::FastWriter将json Value类型格式化,如下代码中的strWrite 就是json格式的字符串(需要post的数据),而不是调用asString()进行转化,后者会导致程序直接崩溃。
Json::FastWriter writer;
std::string strWrite = writer.write(root);
c++利用jsoncpp libcurl 构造http 包(原)的更多相关文章
- SSRF攻击-运用gopher协议构造POST包--emmmm(http://10.112.68.215:10004/index.php?action=login)
还是天枢的一道CTF题,启程! 分析题目,自己注册账户并登陆后,提示输入一个url,网站会自己运行查找网页信息. emmmmm,很挑衅,网站就当作服务器,我们在url框中输 ...
- 利用GBDT模型构造新特征具体方法
利用GBDT模型构造新特征具体方法 数据挖掘入门与实战 公众号: datadw 实际问题中,可直接用于机器学**模型的特征往往并不多.能否从"混乱"的原始log中挖掘到有用的 ...
- 利用VBA+OO4O构造CTAIS开放式通用平台
利用VBA+OO4O构造CTAIS开放式通用平台 2010-06-08 14:59:28 | 来源:税务信息化论文集 | 作者:于非 易飞 摘 要:文立足于CTAIS系统体系,探讨如何通过OO4O技 ...
- 利用Fiddler抓取websocket包
一.利用fiddler抓取websockt包 打开Fiddler,点开菜单栏的Rules,选择Customize Rules... 这时会打开CustomRules.js文件,在class Handl ...
- scapy构造数据包
一.进入scapy交互界面 在终端下输入:scapy ,进入交互界面: 二.查看scapy已经实现的网络协议 ls() 列出scapy中已实现的网络协议 ls(协议类型) 查看某个协议头部字段格式 l ...
- 利用程序随机构造N个已解答的数独棋盘
高级软件工程第二次作业:利用程序随机构造N个已解答的数独棋盘,代码如下: package SudokuGame; /** * 解决这个问题使用的是回溯+剪枝的算法 * 基本思想:不断地将每个格子可填入 ...
- TCP粘包问题的解决方案02——利用readline函数解决粘包问题
主要内容: 1.read,write 与 recv,send函数. recv函数只能用于套接口IO ssize_t recv(int sockfd,void * buff,size_t len,i ...
- JUC包-原子类(AtomicInteger为例)
目录 JUC包-原子类 为什么需要JUC包中的原子类 原子类原理(AtomicInteger为例) volatile CAS CAS的缺点 ABA问题 什么是ABA问题 ABA问题的解决办法 JUC包 ...
- 利用Ant脚本生成war包的详细步骤
使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...
随机推荐
- 手把手教你开发Chrome扩展二:为html添加行为
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 上一节我们 ...
- JAVA OO之 类、对象、包
类 类是具有相同属性和行为的一组对象的集合. public class HomeWork1 { public static void main(String[] args) { MyPhone mp= ...
- python中的is判断引用的对象是否一致,==判断值是否相等
python中的is判断引用的对象是否一致,==判断值是否相等 a = 10 b = 20 list = [1,2,3,4,5] print(a in list) print(b not in lis ...
- [Debug] Node-sass
Meet some problem when trying to install node-sass on windwos. Company has proxy settings, need to r ...
- HDU 5407 CRB and Candies(LCM +最大素因子求逆元)
[题目链接]pid=5407">click here~~ [题目大意]求LCM(Cn0,Cn1,Cn2....Cnn)%MOD 的值 [思路]来图更直观: 这个究竟是怎样推出的.说实话 ...
- cocos2d-x+lua开发模式下编辑器的选择
原本打算直接用CocosIDE的,毕竟是官方出品,并且支持Android远程调试,windows下的调试也非常方便,调试的信息也非常全,智能提示也不错.好了,一切看上去非常完美,可是它有一个致命缺陷, ...
- PB MD5
适用环境:powerbuilder 10.0以后的版本号 window server2003以后的測试可用 PB也能够调用系统自带的DLL 实现MD5 当中md5file对大附件的处理速度也比第三方 ...
- JspSmartUpload 实现上传
2.save 作用:将所有上传文件保存到指定文件夹下,并返回保存的文件个数. 原型:public int save(String destPathName) 和public int save(St ...
- Android关于Task的一些实践之SingleTask, SingleInstance和TaskAffinity
上一篇文章粗略地介绍了一下关于Android中Task的基本知识.只是实践才是检验真理的唯一标准,所以.今天就来试验一下Task中的launchMode是否真的实现了文档所说的那样. 首先.定义三个A ...
- GuiLite 1.2 发布(希望通过这100+行代码来揭示:GuiLite的初始化,界面元素Layout,及消息映射的过程)
经过开发群的长期验证,我们发现:即使代码只有5千多行,也不意味着能够轻松弄懂代码意图.痛定思痛,我们发现:虽然每个函数都很简单(平均长度约为30行),可以逐个击破:但各个函数之间如何协作,却很难说明清 ...