2.13
中央服务器的消息转发过程
中央服务器的消息转发功能依赖于系统路由表,也就是所有客户端在中央服务器上的注册信息。所以消息转发的前提条件是所有需要通信的客户端都已经注册或登录到中央服务器上,并且系统路由信息已经被同步到各个客户端上。正如上节所述,客户端注册、登录以及中央服务器的路由管理和路由同步也属于应用层业务逻辑范畴。
我们在前面消息分发线程MessageDispatcher的介绍中已经了解了MessageDemultiplexer的作用,但是一直没有真正定义和实现。实际上,我们要将MessageDemultiplexer定义为一个抽象类,真正的转发器实现应该从它派生,目的是使得中央服务器的应用层可以替换默认的消息转发器实现,而不需要修改MessageDispatcher的代码。
MessageDemultiplexer定义如
(2009-02-01 11:34)
2.12
系统路由表实现和MONOSTATE模式
如果应用层需要构建三层应用系统甚至四层应用系统,那么就需要启用中央服务器的消息转发功能,以实现客户端之间的消息传递。此时,有些客户端就是真正的客户端(面向普通用户),而另一些客户端则充当业务服务器(或应用服务器)。例如下图所示的三层系统和四层系统的体系结构:

图2-13
三层系统体系结构示例
2.11 框架重构:消息处理器及其注册方法的改进
我们有理由假设客户端或服务器端的应用层需要定义很多的业务消息,这些业务消息不仅可以按相关程度分组,而且有些消息来往比较频繁而有的消息则很少发送。按照逻辑上的相关性或者处理上的方便性,消息分组后可为每一组消息定义一个消息处理器(当然,为每一个消息定义一个消息处理器也未尝不可,但是会导致处理器列表很长,消息分发效率会受到影响,所以不建议这样做!)。那么对于消息的接收端来说,频繁发生的消息就可能需要尽快地分发和处理,也就是尽量提高其分发和处理效率。处理函数的效率在框架层是没法控制的,那么如何提高消息分发的效率呢?
这里提供两个途径,一个方法和一个建议,方法可以在框架层强制实施,但是建议只能由应用层开发人员尽量遵守。这个方法就是:为每个消息处理器规定优先级,就用数字来表示吧,优先级较大的消息处理器将被排
(2009-01-19 13:33)
2.10 框架重构:消息映射表的改进
有了全结构化消息解析器,我们就可以着手改造消息映射表了。
首先,重新定义_MSGMAP_TABLE_ITEM_使其包含全结构化消息解析器接口指针:
|
struct _MSGMAP_TABLE_ITEM_
{
#ifdef _USE_XML_MESSAGE_FORMAT_
const char * m_msgId;
#elif defined(_USE_BINARY_MESSAGE_FORMAT_)
_enum_MessageID m_msgId;
#endif
FullStructuredMessageParser
*m_pFullParser; // 指向解析器对象
|
2.9
全结构化消息解析器
基于现在的消息映射表和消息分发过程,消息处理器的各个消息处理函数只能接受类型为HalfStructuredMessageWrapper或者HalfStructuredMessageSmartPtr的参数。任一消息处理函数的实现框架如下:
|
void ExampleProcessor::OnMessage_X(HalfStructuredMessageWrapper
wrapper)
{
// (1) 如果需要,取出wrapper.pHalfMsg_的消息头的各个信息;
// (2) 逐步解析wrapper.pHalfMsg_的消息体;
// (3) 根据消息ID和消息体的内容决定如何处理该消息,如果需要
&nb
|
(2009-01-19 13:20)
2.8
半结构化消息封装器接口及其实现
显然,对于框架层来说,它不可能预测用户的业务消息内容,因此无法提供一个转换工具,使得用户能够很方便地将一个完全结构化的业务消息转换为半结构化消息甚至直接转换为文本串消息或者二进制字节流消息。此外,所有消息都应看做业务层消息,而且何时发送以及发送什么消息完全由应用层业务逻辑决定,框架层不会发送任何消息。但是框架层可以提供将半结构化消息转换为原始消息(XML文本消息或二进制字节流消息)的工具,即半结构化消息封装器(与半结构化消息解析器对应)。虽然框架不会调用半结构化消息封装器,但是应用层需要调用它。
正常的消息转换顺序如下图所示:
(2009-01-16 14:03)
2.7
消息处理器接口、实现及其注册
消息分发框架应该支持用户定义一个或多个消息处理器类,因为用户的业务消息可能需要分类处理,比如把逻辑相关的消息进行分组,每组消息定义一个消息处理器。对于框架来说,需要一个消息处理器的公共接口和一个消息处理器列表,因为这种情况最适合使用C++的多态机制了。
最容易想到的方法是在MessageProcessor接口中声明一个pure
virtual函数Process():
|
class MessageProcessor
{
public:
virtual BOOL
Process(HalfStructuredMessageSmartPtr psmsg) = 0;
};
|
(2009-01-16 12:52)
2.6 消息分发器
从图2-2和NetworkObserverImpl的实现可以看出,该框架由位于框架层中的一个独立的消息分发线程来驱动,它统一分发所有的半结构化消息,不论该消息是来自于网络还是本地事件。由于每一个消息都赋予了唯一的消息ID,且通信层上报的消息都完成了消息头的解析,所以在此基础上可以基于消息ID和消息映射表来分发。很显然,应该让分发线程持有一个半结构化消息队列和一个消息处理器的列表,这样消息分发线程就可以将每个消息依次投递到各个消息处理器,直到有一个处理器愿意接受并处理该消息(即它预先注册了该消息)。这种消息映射表驱动的思想在很多软件中都使用过,例如MFC。
MessageDispatcher的继承关系如下图所示:

(2009-01-16 11:17)
2.5 半结构化消息解析器接口及其实现
现在来看如何解析XML消息和二进制消息。
XMLMessageParser和BinMessageParser是接口HalfStructuredMessageParser的实现类,它们的关系如下图所示:

图2-5
半结构化消息解析器类层次结构
(2009-01-16 11:04)
2.4 NetworkObserver接口实现
有了消息格式作为基础,就可以实现半结构化消息解析器和接口NetworkObserver了。通信层和框架之间的NetworkObserver接口显然是使用了Observer设计模式。
我们先来看它的实现类定义:
|
class NetworkObserverImpl : public
NetworkObserver
{
public:
NetworkObserverImpl();
private:
virtual void
OnMessage(UserMsgSmartPtr pUserMsg,
&n
|