消息分发机制 当接收到前端发来的消息并解析后 根据包头的消息码来决定分发到哪个模块,以及调用哪个函数
步骤1、需要注册消息码 为了之后找到这个消息码需要干什么事
步骤2、接收到消息并解析后调用根据解析的包头里的消息码到消息管理器里找对应的消息码分发到对应的部件或者函数
步骤3、在对应的部件上面回调写的函数
不多说了直接上代码
// MH_Base.h
#ifndef __MH_Base_h__
#define __MH_Base_h__
// 消息处理者基类
class MH_Base
{
public:
virtual ~MH_Base() {};
virtual void operator()(const void* data, size_t len) = 0;
};
/// 全局或者静态函数
class MH_Function : public MH_Base
{
public:
typedef void (Function1)(const void* data, size_t len);
public:
MH_Function(Function1* func) : _func1(func) {}
virtual void operator()( const void* data, size_t len)
{
_func1( data, len);
}
private:
union
{
Function1* _func1;
};
};
#endif
MH_Base这个类是处理消息体的基类, MH_Function继承这个类, 之后回调的话要用到这个类里面的数据
//MessageManager.h
#ifndef __MessageMgr_h__
#define __MessageMgr_h__
#include <iostream>
#include "MH_Base.h"
/// 所有消息的消息头
struct MessageHeader
{
unsigned short msgKey; /// 消息类型
unsigned short msgId; /// 消息码
};
#define MsgId_Max 100 // 这里先顶一个消息id上限为100 的宏, 正式项目中药根据消息码的增加最大值也跟着增加
class MessageManager
{
public:
MessageManager();
~MessageManager();
public:
virtual bool init();
virtual void unint();
public:
//--消息
void regMessageHandler(unsigned long msgId, MH_Base* mh);
void setMessageHandlerEnable(unsigned long msgId, bool setting);
virtual bool hasMessageHandler(unsigned long msgId) const;
virtual void onMessage(const MessageHeader& hdr, const void* data, size_t len);
protected:
MH_Base* m_msgHandler[MsgId_Max]; // 消息处理函数
unsigned char m_msgHandlerEnable[MsgId_Max]; //是否有效(1有效, 0无效)
unsigned char m_msgHandlerFilter[MsgId_Max]; //是否过滤(1过滤,0不过滤)
};
#endif
// MessageManager.cpp
#include "MessageManager.h"
MessageManager::MessageManager()
{
memset(m_msgHandler, 0, sizeof(m_msgHandler));
memset(m_msgHandlerEnable, 1, sizeof(m_msgHandlerEnable));
memset(m_msgHandlerFilter, 0, sizeof(m_msgHandlerFilter));
}
MessageManager::~MessageManager()
{
}
bool MessageManager::init()
{
// 各个模块注册的时候在这里添加
// 例如商城模块 这里我用的是静态函数的借口, 以后想注册商城相关的消息就在regMsgHandler函数里注册了。
//ShopMessage::regMsgHandler();
return true;
}
void MessageManager::unint()
{
for (int i = 0; i < MsgId_Max; ++i )
{
if ( NULL != m_msgHandler[i])
{
delete m_msgHandler[i];
m_msgHandler[i] = NULL;
}
}
}
void MessageManager::regMessageHandler(unsigned long msgId, MH_Base* mh)
{
if (msgId >= MsgId_Max)
return;
if (m_msgHandler[msgId] != NULL)
{
// 此处警告一下, 这个消息码已经注册过了
//ErrorLn(" msgId=" << msgId << " had register..");
}
m_msgHandler[msgId] = mh;
}
void MessageManager::setMessageHandlerEnable(unsigned long msgId, bool setting)
{
if (msgId >= MsgId_Max)
return;
m_msgHandlerEnable[msgId] = (setting ? 1 : 0);
}
bool MessageManager::hasMessageHandler(unsigned long msgId) const
{
return (msgId < MsgId_Max && m_msgHandler[msgId] != NULL);
}
void MessageManager::onMessage(const MessageHeader& hdr, const void* data, size_t len)
{
if (hdr.msgId >= MsgId_Max)
return;
// 消息处理函数
MH_Base* pFunc = m_msgHandler[hdr.msgId];
if (pFunc == NULL)
return;
// 该消息被临时禁止,可能存在刷数据操作
if (m_msgHandlerEnable[hdr.msgId] == 0)
{
// 需要警告一下
//WarningLn(" msgId=" << hdr.msgId << " disable");
return;
}
// 该消息可能被过滤了,不做处理
if (m_msgHandlerFilter[hdr.msgId] == 1)
{
// 需要警告一下
//WarningLn("msgId = " << hdr.msgId << " filtered");
return;
}
//--消息处理
#ifdef _DEBUG
(*pFunc)(data, len);
#else
try
{
(*pFunc)(data, len);
}
catch (...)
{
ErrorLn("msgFun exect Exception, msgId=" << hdr.msgId << ", len=" << nLen);
}
#endif
}
这里只要是存储注册的消息码和对应的函数, 并进行分发
// main.cpp
#include <iostream>
#include "MessageManager.h"
// 在这里进行测试
// 首先声明 大前提是接收过来的消息已经将包头 和包体解析开了
// 我这里就自己定义一个包头 正常应该是其他端发过来嘚
MessageHeader head;
MessageManager msg;
// 步骤二编写回调函数
void Test_Function(const void* data, size_t len)
{
// 此处随便解析一下, 但是正规项目中需要自己严格处理
int a = *((int*)data);
std::cout << __FUNCTION__ << std::endl;
std::cout << a << std::endl;
}
void Test_Function2(const void* data, size_t len)
{
// 此处随便解析一下, 但是正规项目中需要自己严格处理
int a = *((int*)data);
std::cout << __FUNCTION__ << std::endl;
std::cout << a << std::endl;
}
int main()
{
// 你可以修改1或者2 来决定调用 Test_Function 还是 Test_Function2
head.msgId = 2;
// 暂时无用
head.msgKey = 1001;
// 包体 (包体我没做具体处理)
int a = 10;
// 步骤1 注册消息码
msg.regMessageHandler(1, new MH_Function(&::Test_Function));
msg.regMessageHandler(2, new MH_Function(&::Test_Function2));
// 步骤3 调用函数, 一般是接收到消息统一在一个地方执行
msg.onMessage(head, &a, sizeof(a));
system("pause");
return 0;
}
在这里说明一下。 我这里把消息解析的步骤都省略了。 直接用结构体代替。 我这里只是进行消息的分发机制
调用上面不是很方便。 实际上可以让MessageManager继承一个单例 以后调用的时候就很方便了的