协议

协议结构体定义

struct NetMsgHeader
{
NetMsgLenType BuffLen;	//buff的长度
NetMsgMsgIdType MsgID;	//消息ID
};
//给客户端的消息
struct tagNetMsg :public NetMsgHeader
{
void Serialize(Stream& stream)
{
stream.Write(BuffLen);
stream.Write(MsgID);
stream.WriteBuffer(buff, BuffLen);
}
bool DeSerialize(Stream& stream)
{
if (!stream.Read(BuffLen))
return false;
if (!stream.Read(MsgID))
return false;
if (!stream.ReadBuffer(buff, BuffLen))
return false;
return true;
}

协议注册

//NetMsgHeader Header;
char buff[enMaxMsgDataBufferSize];	//保证最大长度不会超过ServerMsg的buff
/*
* 格式化成字符串输出
*/
void ToString(char* output,int outputsize);
};

typedef bool (*NetMsgProcProtoType)(tagNetMsg& msg);
virtual void RegMsgFun(unsigned int msgID,NetMsgProcProtoType fun,bool isStaticLen,unsigned int DataLen)
{
	assert((msgID > GAME_MSG_BEGIN) && (msgID < GAME_MSG_ID_MAX));
	NetMsgFunction& ele = GetFuncMap()[msgID];
	ele.proc = fun;
	ele.IsStaticDataLen = isStaticLen;
	ele.DataLen = DataLen;
	ele.MsgID = msgID;
}
RegMsgFun(GAME_MSG_HEART_BEAT, NetGate::ServicePlayerHeartBeat, false, 0);

//协议解析

1.Stream解析

//strem类
#pragma once
#include <math.h>
#include <assert.h>
typedef unsigned int uint32;
#ifdef WIN32
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif
#ifndef WIN32
#include <limits>
#endif
#define Max(a,b)            (((a) > (b)) ? (a) : (b))
#ifndef WIN32
#pragma GCC push_options
#pragma GCC optimize("O3")
#endif
class Stream
{
public:
	Stream()
	{
	m_Pos = 0;
	m_MaxBuffSize = 256;
	m_pBuff = new char[m_MaxBuffSize];
	m_bAttach = false;
	}
	Stream(uint32 Size)
	{
	m_Pos = 0;
	m_MaxBuffSize = Size;
	m_pBuff = new char[m_MaxBuffSize];
	m_bAttach = false;
	}
	Stream(char* pBuff,uint32 Size)
	{
	m_Pos = 0;
	m_MaxBuffSize = Size;
	m_pBuff = pBuff;
	m_bAttach = true;	
	}
	~Stream()
	{
	if(m_pBuff && !m_bAttach)
	{
	delete[] m_pBuff;
	m_pBuff = 0;
	}
	}
	void AttachBuffer(char* pBuff,uint32 nSize)
	{
	if(!pBuff && nSize == 0)
	{
	return;
	}
	if(m_pBuff && !m_bAttach)
	{
	delete[] m_pBuff;
	m_pBuff = 0;
	}
	m_bAttach = true;
	m_pBuff = pBuff;
	m_Pos = 0;
	m_MaxBuffSize = nSize;
	}
	uint32 GetBuffSize()
	{
	return m_MaxBuffSize;
	}
	uint32 GetPos()
	{
	return m_Pos;
	}
	void SetPos(uint32 pos)
	{
	m_Pos = pos;
	}
	void WriteBuffer(const char* pBuff,uint32 nSize)
	{
	if(m_Pos + nSize > m_MaxBuffSize)
	{
	if(m_bAttach == false)
	{
	Resize(m_MaxBuffSize + Max(nSize,m_MaxBuffSize / 2));
	}
	else
	{
	assert(false && "Attach上去的缓冲区已经超过大小");
	return;
	}
	}
	memcpy(m_pBuff + m_Pos, pBuff, nSize);
	m_Pos += nSize;
	}
	bool ReadBuffer(char* pBuff,uint32 nSize)
	{
	if(m_Pos + nSize > m_MaxBuffSize)
	{
	return false;
	}
	else
	{
	assert((pBuff + nSize < m_pBuff) || (pBuff >= m_pBuff + m_MaxBuffSize));
	memcpy(pBuff, m_pBuff + m_Pos, nSize);
	m_Pos += nSize;
	return true;
	}
	}
	template<class T>
	void Write( T& m_obj)
	{
	_write_data<T>(m_obj,0); 
	}
	template<class T,void (T::*)(Stream&) > 
	struct s_write_fun;
	template<class T> 
	void _write_data( T& m_obj,s_write_fun<T,&T::Serialize>*)
	{
	m_obj.Serialize(*this); 
	} 
	template<class T> 
	void _write_data( T& m_obj,...)
	{ 
	WriteBuffer((const char*)&m_obj,sizeof(m_obj));
	}
	template<class T,bool (T::*)(Stream&)>
	struct s_read_fun;
	template<class T>
	bool _read_data(T& m_obj,s_read_fun<T,&T::DeSerialize>*)
	{
	return m_obj.DeSerialize(*this);
	}
	template<class T>
	bool _read_data(T& m_obj,...)
	{
	if(m_MaxBuffSize >= m_Pos + sizeof(T))
	{
	//memcpy(&obj,m_pBuff + m_Pos,sizeof(T));
	ReadBuffer((char*)&m_obj,sizeof(T));
	return true;
	}
	else
	{
	return false;
	}
	}
	template<class T>
	bool Read(T& m_obj)
	{
	return _read_data<T>(m_obj,0); 
	}
	private:
	char* m_pBuff;
	uint32 m_MaxBuffSize;
	uint32 m_Pos;
	bool m_bAttach; 
	void Resize(uint32 newSize)
	{
	if(newSize > m_MaxBuffSize)
	{
	char* pNewBuff = new char[newSize];
	memcpy(pNewBuff,m_pBuff,m_Pos + 1);
	delete[] m_pBuff;
	m_pBuff = pNewBuff;
	m_MaxBuffSize = newSize;
	}
	}
};
#ifndef WIN32
#pragma GCC pop_options
#endif

消息结构体定义

#pragma once
#include "Stream.h"
#define MAX_CHAT_DATA_SIZE 512
#define MAX_EXTRA_DATA_SIZE 1024
#pragma pack(push,1)
//聊天消息类型
enum enChatType
{
	enChatType_PRIVATE = 0,								// 私聊
	enChatType_TEAM = 1,								// 队伍
	enChatType_GUILD = 2,								// 帮派
	enChatType_WORLD = 3,								// 世界	
	enChatType_HORN = 4,								// 喇叭
	enChatType_SYSTEM = 5,								// 系统
	enChatType_CENTERS = 6,								// 中央屏幕
	enChatType_FRIEND = 7,								// 好友聊天
	enChatType_STRANGE = 8,								// 陌生人消息
	enChatType_SCENCE = 9,								// 场景聊天
	enChatType_CAMP = 10,								// 国家聊天
	enChatType_RUMOUR = 11,								// 传闻(强化)
	enChatType_TEAMCAMP = 12,							// 组队招募广播
};
struct MsgChat
{
	void Serialize(Stream& stream) 
	{
		stream.Write((char&) m_ChatType);
		stream.Write((char&) m_HornType);
		stream.Write(m_nRecverRoleID);
		unsigned short nLen = (unsigned short)m_strChatData.GetRealStrLen();
		stream.Write(nLen);
		stream.WriteBuffer(m_strChatData.GetName(),nLen);
		unsigned short nNameLen = (unsigned short)m_strRecverRoleName.GetRealStrLen();
		stream.Write(nNameLen);
		stream.WriteBuffer(m_strRecverRoleName.GetName(),nNameLen);
	}

	bool DeSerialize(Stream& stream)
	{
		char nCharType;
		if (!stream.Read(nCharType))
			return false;
		m_ChatType = (enChatType)nCharType;

		char HornType;
		if (!stream.Read(HornType))
			return false;
		m_HornType = (enItemHornType)HornType;

		if (!stream.Read(m_nRecverRoleID))
			return false;

		unsigned short nLen = 0;
		if (!stream.Read(nLen))
			return false;

		if(nLen >= MAX_CHAT_DATA_SIZE - 1)
		{
			return false;
		}

		if (!stream.ReadBuffer(m_strChatData.GetName(), nLen))
			return false;


		if (!stream.Read(m_nExtraDataLen))
			return false;

		if(m_nExtraDataLen >= MAX_EXTRA_DATA_SIZE - 1)
		{
			return false;
		}

		if (!stream.ReadBuffer(m_ExtraData, m_nExtraDataLen))
			return false;

		unsigned short nNameLen = 0;
		if (!stream.Read(nNameLen))
			return false;

		if(nNameLen >= MAX_ROLE_NAME_LEN - 1)
		{
			return false;
		}

		if (!stream.ReadBuffer(m_strRecverRoleName.GetName(), nNameLen))
			return false;

		return true;
	}
	MsgChat():
	m_ChatType((enChatType)0),m_HornType((enItemHornType)0),m_nRecverRoleID((t_RoleID)0)
	{
		m_strChatData.SetName("");
		m_strRecverRoleName.SetName("");
	}
	MsgChat(enChatType nChatType,enItemHornType nHornType,t_RoleID nRecverRoleID,CommonString<MAX_CHAT_DATA_SIZE> strChatData,CommonRoleName strRecverRoleName):
	m_ChatType(nChatType),m_HornType(nHornType),m_nRecverRoleID(nRecverRoleID)
	{
		m_strChatData.SetName(strChatData.GetName());
		m_strRecverRoleName.SetName(strRecverRoleName.GetName());
		m_nExtraDataLen = 0;
	}
	enChatType			m_ChatType;
	enItemHornType		m_HornType;		
	t_RoleID			m_nRecverRoleID;
	CommonString<MAX_CHAT_DATA_SIZE> m_strChatData;
	TUint16		m_nExtraDataLen;
	char		m_ExtraData[MAX_EXTRA_DATA_SIZE];
	CommonRoleName		m_strRecverRoleName;
};
#pragma pack(pop)

接收协议解析

TBool NetGate::ServiceChat( tagNetMsg& msg,WorldPlayer* pWorldPlayer )
{
 	MsgChat msgRecv;
 	Stream stream(msg.buff, msg.BuffLen);
	if(stream.Read(msgRecv) == false)
		return false;

	enChatType MsgType = msgRecv.m_ChatType;
	Tint32 nLenChat = msgRecv.m_strChatData.GetRealStrLen();
}


2.protobuf解析

这个使用很简单,主要就是生成pb


原文地址:https://www.cnblogs.com/byfei/p/6389805.html