nb原创, 欢迎转载,转载请在明显处注明! Thx~
原文地址:http://blog.csdn.net/nilreb_nb/article/details/17162709
关于json在vs2012下的配置和json的用法不清楚的自己去google
json的配置可以参考这篇文章:http://blog.csdn.net/joeblackzqq/article/details/9060385
声明:
1、网络数据的传送都是大端模式,而X86操作系统下的vs2012是使用的小端模式,所以需要进行转换
2、我使用的是unicode编码传送的(utf-16be),其实就是一连串16进制数字。
上面概念不清楚的google去。
3、用封装好的json数据转换成unicode编码,进行传送,这样方便客户端和服务器端的数据处理。
假如现在客户端要发送一个包含中文,包含各种中英文的标点符号的json数据("不不!!@#$%^&*.,;'/?。,、;‘")给服务器,要怎么封装?
老规矩,直接上代码(亲测)
(1)json数据的封装
//send a packet to server
Value root1;
//root1["UserName"] = Value("Mike");
string text1 = "不不!!@#$%^&*.,;'/?。,、;‘";
root1["UserName"] = Value(text1.c_str());
//root1["PassWord"] = Value(123);
//root1["IMEI"] = Value("IMEI_str");
//root1["OS"] = Value("Windows");
//root1["MODELS"] = Value("MODELS_str");
char *LoginReq;//用来存储发送的字节数组,这里只是申明,还没分配内存
int login_total_length=0;
TransCoding_UTF8_TO_UNICODE1(root1,LoginReq,login_total_length,0x0010,WaterNum);
//network judge
cSocket.Send(LoginReq,login_total_length+1,0);//经过上面的函数,LoginReq数组已经分配了内存并且有了发送的数据
delete []LoginReq;
这里声明和定义了一个json对象,要发送一个用户名给服务器,主要是利用TransCoding_UTF8_TO_UNICODE1这个函数来进行转码和封装,这里要释放堆内存delete [] ..(因为我在转码函数里面new了一片内存)。下面来看看它:
//TransCoding From Json To Unicode ( "utf-8" -> "unicode" )
void TransCoding_UTF8_TO_UNICODE1(const Value &root, char* &LoginReq, int &packet_total_length, int CommandID, int &WaterNum)
{
FastWriter fastwriter;
string LoginReq_body = fastwriter.write(root);//把json对象里面的数据转换成string格式
wstring login_body = s2ws(LoginReq_body);//s2ws函数是把中英文混杂的string转换成wstring,在下面会给出代码
char *login_parse = (char *)(&login_body[0]);//因为wstring是宽字节,所以这里给个单字节char指针强制转换一下
//little endian To big endian(大小端的转换,就是把宽字节里面的两个字节换个位置)
for(int i=0;i<wcslen(&login_body[0])*2;i+=2)
{
int temp;
temp = login_parse[i];
login_parse[i] = login_parse[i+1];
login_parse[i+1] = temp;
}
/*for(int i=0;i<wcslen(&login_body[0])*2;i++)
CCLog("%d-(%d)",i+1,login_parse[i]);*///输出看看转换对不对
int login_body_length = wcslen(&login_body[0]);//包体的长度(其实就是json对象的长度)
packet_total_length = login_body_length*2 + 8;//整个数据包的长度(我用的数据包的包头8个字节)
LoginReq = new char[packet_total_length]; //在堆空间搞一个数组来存储数据包(注意参数的生命周期)
memcpy(LoginReq+8,login_parse,wcslen(&login_body[0])*2);//把json数据放到第9个位置,包体开始的位置
//total length(下面的是我的包头信息,8个字节,你可以忽略下面这段代码)
LoginReq[0] = ((packet_total_length > 0xff)?(packet_total_length/(0xff+1)):(0));
LoginReq[1] = ((packet_total_length > 0xff)?(packet_total_length%(0xff+1)):(packet_total_length));
//version number
LoginReq[2] = 0x00;
LoginReq[3] = 0x01;
//command ID
LoginReq[4] = ((CommandID > 0xff)?(CommandID/(0xff+1)):(0));
LoginReq[5] = ((CommandID > 0xff)?(CommandID%(0xff+1)):(CommandID));
//waterNum
LoginReq[6] = ((WaterNum > 0xff)?(WaterNum/(0xff+1)):(0));
LoginReq[7] = ((WaterNum > 0xff)?(WaterNum%(0xff+1)):(WaterNum));
WaterNum++;
if(WaterNum>9999)
WaterNum = 1000;
}
给出s2ws代码
inline wstring s2ws(const string& s)
{
setlocale(LC_ALL, "chs");
const char* _Source = s.c_str();
size_t _Dsize = s.size() + 1;
wchar_t *_Dest = new wchar_t[_Dsize];
wmemset(_Dest, 0, _Dsize);
mbstowcs(_Dest,_Source,_Dsize);
std::wstring result = _Dest;
delete []_Dest;
setlocale(LC_ALL, "C");
return result;
}
这样就在客户端把一个json对象的数据通过unicode编码发送给了服务器端
(2)json数据的解析
现在服务器传过来一连串的unicode编码的json对象,要怎么解析呢?这个就简单多了,看代码。
//parse receive_data
//---------------------------------------------
string str11 = TransCoding_UNICODE_TO_UTF81(dataBuf,packet_len);//直接用一个string来接收解析完的数据
Reader reader;
Value json_object;
if (!reader.parse(str11.c_str(), json_object)) //然后用json自带的解析器来解析
CCLog("json parse failed!");
CCLog("11-%s",json_object["name"].asCString());
CCLog("11-%d",json_object["age"].asInt());
//---------------------------------------------
//TransCoding From Unicode To Json ( "unicode" -> "utf-8" )
string TransCoding_UNICODE_TO_UTF81(char* dataBuf, const int packet_len)
{
//big endian To little endian//同样要进行大小端的转换
for(int i = 0; i<packet_len-1;i+=2)
{
int temp;
temp = dataBuf[i];
dataBuf[i] = dataBuf[i+1];
dataBuf[i+1] = temp;
}
wchar_t *parse = (wchar_t *)(dataBuf+8);//一样要进行强制转换一下
return ws2s(parse);
}
下面给出ws2s函数代码
inline string ws2s(const std::wstring& ws)
{
std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";
setlocale(LC_ALL, "chs");
const wchar_t* _Source = ws.c_str();
size_t _Dsize = 2 * ws.size() + 1;
char *_Dest = new char[_Dsize];
memset(_Dest,0,_Dsize);
wcstombs(_Dest,_Source,_Dsize);
std::string result = _Dest;
delete []_Dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}
这样客户端就成功接收到了服务器端的json数据。