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

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_UNICODE_TO_UTF81函数的转码实现

//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数据。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值