2.6 消息分发器
从图2-2和NetworkObserverImpl的实现可以看出,该框架由位于框架层中的一个独立的消息分发线程来驱动,它统一分发所有的半结构化消息,不论该消息是来自于网络还是本地事件。由于每一个消息都赋予了唯一的消息ID,且通信层上报的消息都完成了消息头的解析,所以在此基础上可以基于消息ID和消息映射表来分发。很显然,应该让分发线程持有一个半结构化消息队列和一个消息处理器的列表,这样消息分发线程就可以将每个消息依次投递到各个消息处理器,直到有一个处理器愿意接受并处理该消息(即它预先注册了该消息)。这种消息映射表驱动的思想在很多软件中都使用过,例如MFC。
MessageDispatcher的继承关系如下图所示:
图2-6 消息分发线程类继承关系
线程模型Thread类的实现请参考后面第4章“线程封装及其对象模型”一节。
接口MessageReceiver定义如下:
class MessageReceiver { public: virtual void ReceiveMessage(HalfStructuredMessageSmartPtr psmsg, CommunicationUnitID unitId = 0, UserMsgSmartPtr puserMsg = UserMsgSmartPtr()) = 0; }; |
从该接口以及NetworkObserverImpl的实现可以看出,消息队列中将要放置的不仅仅是半结构化消息,还有该消息的来源以及对应的原始字节流消息。因为客户端和服务器将共用框架中的分发线程类,而服务器有可能充当客户端之间的消息转发器,所以在原始消息被解析为半结构化消息之后还需要保留原始消息以及上报该消息的通信单元ID,这个通信单元ID在服务器端标明了该消息是来自哪个客户端的。而在客户端后两项信息都可以忽略。
MessageDispatcher类定义如下:
class MessageDispatcher : public Thread, public MessageReceiver { DECLARE_STATIC_SINGLETON(MessageDispatcher) public: virtual void stop(); // 重写Thread::stop() private: // method from interface MessageReceiver virtual void ReceiveMessage(HalfStructuredMessageSmartPtr psmsg, CommunicationUnitID unitId, UserMsgSmartPtr puserMsg); virtual void _Run(); // 重写Thread::_Run() void _Dispatch(HalfStructuredMessageWrapper wrapper); void _Default(); // 出错时的默认处理,一般为断言或记日志 private: _HalfStructuredMessageQueue m_msgQueue; // 半结构化消息队列 #ifdef _CENTRAL_SERVER_ MessageDemultiplexer *m_theDemultiplexer;// 消息转发和分发对象 #else MessageProcessorList m_processorList; // 消息处理器列表 #endif }; typedef MessageDispatcher MessageDispatcherFactory; |
半结构化消息队列_HalfStructuredMessageQueue定义为一个同步队列:
typedef SyncQueue<HalfStructuredMessageWrapper> / _HalfStructuredMessageQueue; |
其元素类型为HalfStructuredMessageWrapper,定义如下:
struct HalfStructuredMessageWrapper { HalfStructuredMessageWrapper() : pHalfMsg_(NULL), unitFrom_(0), pUserMsg_(NULL) { } HalfStructuredMessageWrapper(HalfStructuredMessageSmartPtr phsmsg, CommunicationUnitID unitId, UserMsgSmartPtr puserMsg) : pHalfMsg_(phsmsg), unitFrom_(unitId), pUserMsg_(puserMsg) { } HalfStructuredMessageSmartPtr pHalfMsg_; CommunicationUnitID unitFrom_; UserMsgSmartPtr pUserMsg_; }; |
MessageDispatcher作为客户端和服务器共用的一个类,在服务器端进行消息分发之前,可以直接完成消息的转发而不需要应用层消息处理器的参与,而消息分发仅仅针对不需要转发的消息和消息处理器进行。所以我们引入一个标志宏_CENTRAL_SERVER_和一个在中央服务器端专门负责消息转发和分发的对象MessageDemultiplexer,并在编译中央服务器框架和应用层代码前于命令行中定义该宏,如果没有定义则认为是任一客户端。当MessageDispatcher用于中央服务器时将包含一个MessageDemultiplexer对象,后者则包含消息处理器列表;当MessageDispatcher类用于客户端时将直接包含消息处理器列表。
在中央服务器端,消息转发和分发框架的逻辑可用下图表示:
图2-7 中央服务器的消息分发逻辑
MessageDispatcher类的各个函数实现如下:
MessageDispatcher::MessageDispatcher() { #ifdef _CENTRAL_SERVER_ m_theDemultiplexer = MessageDemultiplexerFactory::get_instance(); #endif
this->start(); // 自动启动分发线程 } void MessageDispatcher::ReceiveMessage(HalfStructuredMessageSmartPtr psmsg, CommunicationUnitID unitId, UserMsgSmartPtr puserMsg) { HalfStructuredMessageWrapper theWrap(psmsg, unitId, puserMsg); m_msgQueue.push(theWrap); this->notify(FALSE); // 通知分发线程 } void MessageDispatcher::stop() { m_msgQueue.clear(); Thread::stop(); } void MessageDispatcher::_Run() { while (TRUE) { _MutexLocker guard(m_mutex); if (m_status == THREAD_ACTIVE) { if (m_msgQueue.empty()) { this->waiting(); // wait to be wakeup } else { HalfStructuredMessageWrapper theMsgWrapper; if (m_msgQueue.pop(theMsgWrapper)) this->_Dispatch(theMsgWrapper); else // pop msg failed! this->waiting(); } } else if (m_status == THREAD_SUSPEND) { this->waiting(); } else { break; } }// end while } |
在第一次获得MessageDispatcher单例对象的时候,分发线程将自动启动并开始从消息队列中取出消息进行分发。通常在需要向半结构化消息队列中放入消息时才需要分发线程对象,不论是网络消息还是本地消息,例如NetworkObserverImpl类的函数实现。
下一节我们先来看消息处理器的接口、消息处理器的实现及其注册、消息映射表的构建,因为MessageDispatcher::_Dispatch()函数的实现以及中央服务器端的MessageDemultiplexer类实现都依赖于这些基础设施。关于MessageDemultiplexer及其实现,请参考本章2.13节。