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