2 {
3 // 转换消息
4 NetMessageCaptureRecievedMsg(NetMessagemsg); // 在交给处理器之前
5 NetMessageCaptureBeforeSendMsg(NetMessagemsg); // 在发送出去之前
6
7 bool Enabled{ get ; set ;} // 是否启用本Hook
8 }
通过 INetMessageHook 接口可以看到,当消息进入系统时回被 CaptureRecievedMsg 方法截获(比如,进行解密处理),当把消息发送到网络之前,将被 CaptureBeforeSendMsg 方法截获(比如,进行加密处理)。
如果有多个
INetMessageHook
,则可以形成一个
HookList
,消息经过
HookList
时,分别按顺序被每个
INetMessageHook
处理,
ESFramework
中的
HookList
的参考实现是
EsbNetMessageHook
,并且它也实现了
INetMessageHook
接口,这样就可以把一个
Hook
链当作一个
Hook
了。
其源码如下:

需要特别注意的是, HookList 的实现中,逐个调用 Hook 的 CaptureRecievedMsg 方法的顺序必须与逐个调用 CaptureBeforeSendMsg 方法的顺序相反,这就是为什么 EsbNetMessageHook 实现 CaptureBeforeSendMsg 方法时,出现下列代码的原因:
为了说明为什么需要颠倒
Hook
链的情况,可以举个例子,假设有一个“原始消息”从系统
1
发送到系统
2
,其间经过了两个
Hook
,一个加密
Hook
,一个是压缩
Hook
,则可表示如下:
系统
1
=》原始消息=》加密=》压缩=》发送
系统
2
=》接收消息=》解压缩=》解密=》原始消息
还要提醒的是,在具体的
Hook
实现中,截获处理经常改变
Body
的大小,如果
Body
的大小真的发生了变化,一定要更新消息头(
IMessageHeader
)中的
MessageBodyLength
字段。
通常,采用Hook时,服务端与客户端是对称的,所以你可以把所有的Hook实现放在一个Dll中,这样服务端和客户端可以共同使用这个Hook Dll了。
由于对网络消息进行压缩是常见的需求,所以我把
BaseZipHook
纳入到了
ESFramework
中,并且,这也是
IMessageHeader
存在
ZipMe
属性的原因。
ZipMe
属性用于通知
BaseZipHook
是否对接收到的本条消息进行解压缩,是否在发送本消息之前进行压缩。
BaseZipHook
实现如下:

BaseZipHook 是一个抽象类,具体实现的压缩算法由派生类通过覆写 Zip 和 Unzip 方法提供。如果要实现一个具体的 ZipHook ,你可以从 BaseZipHook 继承,并采用 ZipHelper 提供的压缩 / 解压缩功能。
到现在为止,我们已经讨论了关于消息的比较多的内容了,但还有一个非常重要的组件没有讲到,那就是消息分派器
ITcpStreamDispatcher
,消息分派器直接与
Tcp
组件或
Udp
组件联系,并且所有消息的进出都要经过
ITcpStreamDispatcher
,所以分派器是一个对消息进行
Hook
的理想位置,并且消息分派器会把具体的消息分派到对应的消息处理器上。欲知道
ITcpStreamDispatcher
的原理与实现,请继续关注下文:
ESFramework
介绍之(
5
)
――
消息分派器
ITcpStreamDispatcher
上一篇:
ESFramework介绍之(3)――消息处理器和处理器工厂
转到:
ESFramework 可复用的通信框架(序)