协议结构体定义
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