cocos2d-x 3.0 (vs2012环境下亲测)把json数据转换成unicode编码来传送用户数据并且实现json数据的解析和封装

来源:互联网 发布:将js文件引入html代码 编辑:程序博客网 时间:2024/05/19 13:16

原文地址: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数据的封装

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //send a packet to server  
  2. Value root1;  
  3. //root1["UserName"] = Value("Mike");  
  4. string text1 = "不不!!@#$%^&*.,;'/?。,、;‘";  
  5. root1["UserName"] = Value(text1.c_str());  
  6. //root1["PassWord"] = Value(123);  
  7. //root1["IMEI"] = Value("IMEI_str");  
  8. //root1["OS"] = Value("Windows");  
  9. //root1["MODELS"] = Value("MODELS_str");  
  10. char *LoginReq;//用来存储发送的字节数组,这里只是申明,还没分配内存  
  11. int login_total_length=0;  
  12. TransCoding_UTF8_TO_UNICODE1(root1,LoginReq,login_total_length,0x0010,WaterNum);  
  13. //network judge  
  14. cSocket.Send(LoginReq,login_total_length+1,0);//经过上面的函数,LoginReq数组已经分配了内存并且有了发送的数据  
  15. delete []LoginReq;  


这里声明和定义了一个json对象,要发送一个用户名给服务器,主要是利用TransCoding_UTF8_TO_UNICODE1这个函数来进行转码和封装,这里要释放堆内存delete [] ..(因为我在转码函数里面new了一片内存)。下面来看看它:


[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //TransCoding From Json To Unicode ( "utf-8" -> "unicode" )  
  2. void TransCoding_UTF8_TO_UNICODE1(const Value &root, char* &LoginReq, int &packet_total_length, int CommandID, int &WaterNum)  
  3. {  
  4.     FastWriter fastwriter;  
  5.     string LoginReq_body = fastwriter.write(root);//把json对象里面的数据转换成string格式  
  6.     wstring login_body = s2ws(LoginReq_body);//s2ws函数是把中英文混杂的string转换成wstring,在下面会给出代码  
  7.     char *login_parse = (char *)(&login_body[0]);//因为wstring是宽字节,所以这里给个单字节char指针强制转换一下  
  8.     //little endian To big endian(大小端的转换,就是把宽字节里面的两个字节换个位置)  
  9.     for(int i=0;i<wcslen(&login_body[0])*2;i+=2)  
  10.     {  
  11.         int temp;  
  12.         temp = login_parse[i];  
  13.         login_parse[i] = login_parse[i+1];  
  14.         login_parse[i+1] = temp;  
  15.     }  
  16.     /*for(int i=0;i<wcslen(&login_body[0])*2;i++) 
  17.         CCLog("%d-(%d)",i+1,login_parse[i]);*///输出看看转换对不对  
  18.     int login_body_length = wcslen(&login_body[0]);//包体的长度(其实就是json对象的长度)  
  19.     packet_total_length = login_body_length*2 + 8;//整个数据包的长度(我用的数据包的包头8个字节)  
  20.     LoginReq = new char[packet_total_length]; //在堆空间搞一个数组来存储数据包(注意参数的生命周期)  
  21.     memcpy(LoginReq+8,login_parse,wcslen(&login_body[0])*2);//把json数据放到第9个位置,包体开始的位置  
  22.     //total length(下面的是我的包头信息,8个字节,你可以忽略下面这段代码)  
  23.     LoginReq[0] = ((packet_total_length > 0xff)?(packet_total_length/(0xff+1)):(0));  
  24.     LoginReq[1] = ((packet_total_length > 0xff)?(packet_total_length%(0xff+1)):(packet_total_length));  
  25.     //version number  
  26.     LoginReq[2] = 0x00;  
  27.     LoginReq[3] = 0x01;  
  28.     //command ID  
  29.     LoginReq[4] = ((CommandID > 0xff)?(CommandID/(0xff+1)):(0));  
  30.     LoginReq[5] = ((CommandID > 0xff)?(CommandID%(0xff+1)):(CommandID));  
  31.     //waterNum  
  32.     LoginReq[6] = ((WaterNum > 0xff)?(WaterNum/(0xff+1)):(0));  
  33.     LoginReq[7] = ((WaterNum > 0xff)?(WaterNum%(0xff+1)):(WaterNum));  
  34.     WaterNum++;  
  35.     if(WaterNum>9999)  
  36.         WaterNum = 1000;  
  37. }  

给出s2ws代码

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. inline wstring s2ws(const string& s)  
  2. {  
  3.     setlocale(LC_ALL, "chs");   
  4.     const char* _Source = s.c_str();  
  5.     size_t _Dsize = s.size() + 1;  
  6.     wchar_t *_Dest = new wchar_t[_Dsize];  
  7.     wmemset(_Dest, 0, _Dsize);  
  8.     mbstowcs(_Dest,_Source,_Dsize);  
  9.     std::wstring result = _Dest;  
  10.     delete []_Dest;  
  11.     setlocale(LC_ALL, "C");  
  12.     return result;  
  13. }  

这样就在客户端把一个json对象的数据通过unicode编码发送给了服务器端



(2)json数据的解析

现在服务器传过来一连串的unicode编码的json对象,要怎么解析呢?这个就简单多了,看代码。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //parse receive_data  
  2.         //---------------------------------------------  
  3.            string str11 = TransCoding_UNICODE_TO_UTF81(dataBuf,packet_len);//直接用一个string来接收解析完的数据  
  4.         Reader reader;    
  5.         Value json_object;    
  6.         if (!reader.parse(str11.c_str(), json_object))  //然后用json自带的解析器来解析  
  7.             CCLog("json parse failed!");  
  8.         CCLog("11-%s",json_object["name"].asCString());  
  9.         CCLog("11-%d",json_object["age"].asInt());  
  10.         //---------------------------------------------  



这里关键的就是TransCoding_UNICODE_TO_UTF81函数的转码实现

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //TransCoding From Unicode To Json ( "unicode" -> "utf-8" )  
  2. string TransCoding_UNICODE_TO_UTF81(char* dataBuf, const int packet_len)  
  3. {  
  4.     //big endian To little endian//同样要进行大小端的转换  
  5.     for(int i = 0; i<packet_len-1;i+=2)  
  6.     {  
  7.         int temp;  
  8.         temp = dataBuf[i];  
  9.         dataBuf[i] = dataBuf[i+1];  
  10.         dataBuf[i+1] = temp;  
  11.     }  
  12.     wchar_t *parse = (wchar_t *)(dataBuf+8);//一样要进行强制转换一下  
  13.     return ws2s(parse);  
  14. }  

下面给出ws2s函数代码

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. inline string ws2s(const std::wstring& ws)  
  2. {  
  3.     std::string curLocale = setlocale(LC_ALL, NULL);        // curLocale = "C";  
  4.     setlocale(LC_ALL, "chs");  
  5.     const wchar_t* _Source = ws.c_str();  
  6.     size_t _Dsize = 2 * ws.size() + 1;  
  7.     char *_Dest = new char[_Dsize];  
  8.     memset(_Dest,0,_Dsize);  
  9.     wcstombs(_Dest,_Source,_Dsize);  
  10.     std::string result = _Dest;  
  11.     delete []_Dest;  
  12.     setlocale(LC_ALL, curLocale.c_str());  
  13.     return result;  
  14. }  


这样客户端就成功接收到了服务器端的json数据。
0 0
原创粉丝点击