游戏网络通信数据解析-3

设计一个或几个类来解读数据:
部分实现:

class EnCode
{
private:
	char un[2]{};//解决内存对齐
public:
	char index = 0;
	char op = 0;
	union
	{
		char dataPool[0x8];
		int lenth;
		char byte;
		short stval;
		int val;
		float fval;
		double dbval;
		long long lval{};
	};
	char* pointer= 0;
public:
	EnCode(char* &buff, unsigned &len, char EnIndex=0);
	~EnCode();
};

 暂时设置的解析方式

DATA_DESC data_desc[2][9]{};

void init_datadecs()
{
	data_desc[0][0] = { "none",0 };
	data_desc[0][1] = { "short",2 };
	data_desc[0][2] = { "int",4 };
	data_desc[0][3] = { "int64",8 };
	data_desc[0][4] = { "float",4 };
	data_desc[0][5] = { "int64",8 };
	data_desc[0][6] = { "char",1 };
	data_desc[0][7] = { "wchar_t*",4 };
	data_desc[0][8] = { "int64",8 };

	data_desc[1][0] = { "none",0 };
	data_desc[1][1] = { "short",2 };
	data_desc[1][2] = { "int",4 };
	data_desc[1][3] = { "int64",8 };
	data_desc[1][4] = { "float",4 };
	data_desc[1][5] = { "int64",8 };
	data_desc[1][6] = { "char*",4 };
	data_desc[1][7] = { "wchar_t*",4 };
	data_desc[1][8] = { "int64",8 };
}

主要字符编码转化容易掉大坑 

bool OnloginOk(char*& buff, unsigned& len)
{
	CStringA txt;
	CStringA tmp;
	CString utmp;
	PDATALOGINOK _p = (PDATALOGINOK)&buff[1];
	if (_p->RoleCount > 0)
	{
		char* buffStart = buff + 1 + sizeof(DATA_LOGIN_OK);
		char* buffEnd = buff + len;

		while (buffStart < buffEnd)
		{
			EnCode* _coder = new EnCode(buffStart, len);
			tmp.Format("[%s]", data_desc[_coder->index][_coder->op].name);
			txt = txt + tmp;

			if (_coder->op == 0x7)
			{
				utmp = (wchar_t*)_coder->pointer;
				tmp = utmp;
				txt = txt + tmp;
			}
			else
			if (_coder->op == 0x3)
			{
				tmp.Format("[%f]", _coder->fval);
				txt = txt + tmp;


			}
			else {
				tmp.Format("[%d]", _coder->val);
					txt = txt + tmp;
			}
		}
		myAnly->sendData(MTYPE::I_DIS, 0, txt.GetBuffer(), txt.GetAllocLength()+1);
	}
	return true;
}

已经能粗略解析出来了 

然后就要把这个东西定义成一个结构体
这个结构体不能直接这样写

 直接定义将来处理的时候不好处理,比较好的方法就是用现在这个结构体去派生一个类,在派生类里实现自己的类型,要是之后模拟数据涉及到数据打包,结构体里有数据的内容就直接一步到位包回去了

class GBYTE :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator char();
};

class GSHORT :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator short();
};
class GINT :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator int();
};

class GFLOAT :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator float();
};
class GINT64 :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator long long();
};
class GDOUBLE :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator double();
};

class GCAHR :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator const char* ();
};
class GUTF16 :public EnCode
{
	using EnCode::EnCode;//调用构造
public:
	operator const wchar_t* ();
};
EnCode::~EnCode()
{
	if (pointer)delete[]pointer;
	//delete[] buffer;
}

GBYTE::operator char()
{
	return this->byte;
}
GSHORT::operator short()
{
	return this->stval;
}
GINT::operator int()
{
	return this->val;
}
GFLOAT::operator float()
{
	return this->fval;
}
GINT64::operator long long()
{
	return this->lval;
}
GDOUBLE::operator double()
{
	return this->dbval;
}
GCAHR::operator const char* ()
{
	return this->pointer;
}
UTF16::operator const wchar_t* ()
{
	return (wchar_t*)this->pointer;
}

直接定义类型 开始套娃

再来定义个结构体

typedef struct ROLE_DATA
{
	GBYTE byte;
	GINT un;
	GINT un1;
	GUTF16  name;
	GUTF16 infos;
	GINT un2;
	GINT64 un3;
};

然后处理构造函数
测试下效果:

void NetClient::longinok(ROLE_DATA* roles, int count)
{
    CString txt;
    CString tmp;
    txt.Format(L"游戏登录成功!角色数量[%d]\r\n", count);
    for (int i = 0; i < count; i++)
    {
        tmp.Format(L"byte=%d\r\n", (char)roles[i].byte);
        txt += tmp;
        tmp.Format(L"un=%d\r\n", (int)roles[i].un);
        txt += tmp;
        tmp.Format(L"un1=%d\r\n", (int)roles[i].un1);
        txt += tmp;
        tmp.Format(L"name=%s\r\n", (const wchar_t*)roles[i].name);
        txt += tmp;
        tmp.Format(L"infos=%s\r\n", (const wchar_t*)roles[i].infos);
        txt += tmp;
        tmp.Format(L"un2=%d\r\n", (int)roles[i].un2);
        txt += tmp;
        tmp.Format(L"un3=%d\r\n", (long long)roles[i].un3);
        txt += tmp;


    }
    AfxMessageBox(txt);
}

解析出来了 

给派生类重载完运算符后,测试下(不过没啥用,测试写的)只是看看有没有用

bool OnloginOk(char*& buff, unsigned& len)
{
	

	PDATALOGINOK _p = (PDATALOGINOK)&buff[1];

	ROLE_DATA* roleDatas = nullptr;
	if (_p->RoleCount > 0)
	{
		char* buffStart = buff + 1 + sizeof(DATA_LOGIN_OK);
		
		winSock->AnlyBuff(buffStart,buff+len);

		roleDatas = new ROLE_DATA[_p->RoleCount];//创建人物数量个解析数据
		for (int i = 0; i < _p->RoleCount; i++)
		{
			roleDatas[i].byte=buffStart;//重载
			roleDatas[i].un=buffStart;
			roleDatas[i].un1=buffStart;
			roleDatas[i].name=buffStart;
			roleDatas[i].infos=buffStart;
			roleDatas[i].un2=buffStart;
			roleDatas[i].un3=buffStart;
		}
		
	}
	Client->longinok(roleDatas, _p->RoleCount);//
	return true;
}

解析的优化:

	CStringA txt;
	CStringA tmp;
	CString utmp;
	EnCode _coder;

	GBYTE* _bytecoder;
	GSHORT* _shortcoder;
	GINT* _intcoder;
	GFLOAT* _floatcoder;
	GDOUBLE* _doublecoder;
	GCHAR* _asccoder;
	GUTF16* _utfcoder;
	GINT64* _int64coder;

	while (start < end)
	{
		_coder.Init(start,index);
		CStringA _opname = data_desc[_coder.index][_coder.op].name;
		tmp.Format("%s %s;//", data_desc[_coder.index][_coder.op].name, _opname.MakeLower());//转小写
		txt = txt + tmp;
		if (_coder.index == 0)
		{
			switch (_coder.op)
			{
			case 1:
				_shortcoder = (GSHORT*)&_coder;
				tmp.Format("%d\r\n",_shortcoder->value());
				txt = txt + tmp;
				break;
			case 2:
				_intcoder = (GINT*)&_coder;
				tmp.Format("%d\r\n", _intcoder->value());
				txt = txt + tmp;
				break;
			case 4:
				_floatcoder = (GFLOAT*)&_coder;
				tmp.Format("%f\r\n", _floatcoder->value());
				txt = txt + tmp;
				break;
			case 6:
				_bytecoder = (GBYTE*)&_coder;
				tmp.Format("%d\r\n", _bytecoder->value());
				txt = txt + tmp;
				break;
			case 7:
				_utfcoder = (GUTF16*)&_coder;
				utmp.Format(L"[%s]\r\n", _utfcoder->value());
				tmp = utmp;//省的写类型转换
				txt = txt + tmp;
				break;
			case 3:
			case 5:
			case 8:
				_int64coder = (GINT64*)&_coder;
				tmp.Format("%.i64d\r\n", _int64coder->value());
				txt = txt + tmp;
				break;

			}
		}
	}
	myAnly->sendData(MTYPE::I_DIS, 0, txt.GetBuffer(), txt.GetAllocLength() + 1);

 这样到时候要定义结构体的时候就可以直接copy了。

接下来就要把角色数据做到类里面去维护

通过比对中间数据的字符串:
38个是等级
13是宗族

结构是 key,value;key,value;.......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#A#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值