在ESFramework 4.0 进阶(04)-- 驱动力:通信引擎(下)一文末尾我们已经将通信引擎以及整个消息骨架流程组装起来了,只要通信引擎一接收到消息,框架就会按照规定的流程进行运转。到这里,自然想到一个问题,如何来发送消息了?没有发送,何谈接收,就更不会有后续的驱动整个消息处理的骨架流程了。
一.发送消息时遇到的问题
在ESFramework 4.0 进阶(03)-- 驱动力:通信引擎(上)一文中学习引擎接口时,我们知道,各种引擎都提供了发送消息的方法,向服务端引擎IServerEngine的SendMessageToClient方法和PostMessageToClient方法,以及客户端引擎IPassiveEngine的SendMessageToServer方法。我们可以直接调用它们来发送构造好的消息,但是可能会引发两个问题:
(1)由于我们的消息加密、压缩等环节都位于MessagePipe的MessageTransformer组件中,如果直接调用通信引擎发送消息,则该消息不会参与这些变换。
(2)同样的,这些被直接发送的消息也不会被InnerMessageSpy和GatewayMessageSpy监控到。
也就是说,使用通信引擎直接发送消息时,就绕过了MessagePipe,也就破坏了ESFramework规定好的骨架流程,这可能会导致一些严重的后果。比如,在某个项目中,我们挂接了一个InnerMessageSpy,原本期望是拦截所有发送出去的“明文”消息,结果却有一些漏网之鱼;原本我们期望所有的消息都是经过MessageTransformer加密后再发送,结果有些消息以明文的形式发送到了网络上。
怎么办了?使用正规消息发送器IRegularSender,所谓“正规”的意思,就是它会保证消息在被通信引擎发送到网络之前,必须经过MessagePipe。
二.正规消息发送器
我们可以通过以下经过增强的骨架流程图来更清楚地展示IRegularSender在骨架流程中的作用:
IRegularSender在NakeDispatcher与MessagePipe之间切入,将要发送的消息传递给MessagePipe,正如NakeDispatcher将消息处理器返回的消息传递给MessagePipe一样。这样就保证了所有的消息的发送都是完全一致的,且都遵守了ESFramework规定的流程。
你也许会说,如果有些类型消息不是很重要,我不想经过MessageTransformer来加密它们以节约CPU时间,那该怎么办了?其实很容易,首先MessgePipe和MessageTransformer是必须经过的,但是你可以在MessageTransformer中配置某些消息类型,只要MessageTransformer遇到这些类型的消息,就不对起做任何变换,直接返回原始消息即可。ESFramework.Core.BaseMessageTransformer抽象类就为你内置了这一功能,你的MessageTransformer只要从其继承即可。这样一来,就既解决了问题,又保证了骨架流程不被破坏。
三.服务端正规消息发送器
服务端正规消息发送器接口ESFramework.Server.IRegularSender以及其实现类ESFramework.Server.RegularSender,用于保证服务端给客户端发送的消息遵守ESFramework骨架流程。我们来看看ESFramework.Server.RegularSender的类图:
(1)RegularSender有两个public重载的方法,用于将消息发送或投递给N个用户,通过参数UserID指明要将消息发送的目的对象。而我们知道,通过IServerEngine发送消息时,其接收的参数是用户地址UserAddress,所以RegularSender必须借助于用户管理器IUserManager,以根据UserID获取其对应的UserAddress。
(2)RegularSender依赖于MessagePipe就很容易理解了,正是要让消息经过MessagePipe才能算是保证了骨架流程。
(3)RegularSender还提供了一个protected的virtual方法SendMessageToForeigner,这个方法默认实现是什么事情都不做:
{
}
这个方法有什么用了?它被用于ESPlatform,当有很多台应用服务器做Cluster时,某个需要接收该消息的在线用户可能是位于另外一台服务器上,那么,在ESPlatform中,我们只要override这个方法,就可以实现跨应用服务器的消息发送。具体细节我们将在详细介绍ESPlatform时讨论。
通过下面的代码,我们来实例化一个服务端的正规消息发送器实例:
IMessagePipe messagePipe = ......;
IUserManager userManager = ......;
RegularSender regularSender = new RegularSender();
regularSender.MessagePipe = messagePipe;
regularSender.UserManager = userManager;
regularSender.ServerEngine = serverEngine;
//发送消息
IMessage message = null ;
regularSender.SendMessage(message, "aa01");
关于如何构造服务端引擎实例、用户管理器实例以及消息管道实例,可以参见《ESFramework 4.0 进阶》系列的前面几篇文章。
四.客户端正规消息发送器
服务端正规消息发送器接口ESFramework.Passive.IRegularSender以及其实现类ESFramework.Passive.RegularSender,用于保证客户端提交给服务器的消息都遵守ESFramework骨架流程。我们来看看ESFramework.Passive.RegularSender的类图:
客户端的RegularSender相对更简单一些,消息始终是被提交到服务器,即使是P2P消息,也是通过服务器来中转(关于通过P2P Channel发送P2P消息,我们将通过后面即将介绍的MessageTransceiver来解决)。
最后,我们来构造一个客户端正规消息发送器实例:
IMessagePipe messagePipe = ......;
RegularSender regularSender = new RegularSender();
regularSender.MessagePipe = messagePipe;
regularSender.PassiveEngine = passiveEngine;
//发送消息到服务器
IMessage message = null ;
regularSender.SendMessage(message, DataPriority.Common);
好了,正规消息发送器就介绍完毕了。通常,在服务端发送消息都是使用RegularSender,但是在客户端开发时却很少直接使用它,替而代之的是使用IServerAgent和IMessageTransceiver,IServerAgent是ESFramework给出的消息同步调用方案,而IMessageTransceiver则向使用者屏蔽了在发送P2P消息时,是使用的P2P Channel直接发送的还是经过服务器中转的。接下来的文章中,我们就来一个个介绍它们。敬请关注,谢谢。