有些使用ESFramework/ESPlus进行二次开发的朋友,经常来询问要如何做才能在服务端监控客户端发送的所有或部分重要的自定义信息了?鉴于这是一个比较常见的需求,所以,这里我们就简单介绍一下如何在基于ESFramework/ESPlus开发的系统上增加信息监控的功能。
正如ESFramework 开发手册(01) -- 发送和处理信息一文所介绍的,客户端是使用ESPlus.Application.CustomizeInfo.ICustomizeOutter来发送自定义信息的。
该接口的所有方法可以分为两类:一类方法是接收自定义信息的目标用户是服务端;另一类是接收自定义信息的目标用户是其他在线用户。无论是哪种情况,信息都会到达服务端,或由服务端处理、或经服务端转发。(如果客户端之间开启了P2P通道,则稍后再谈。)所以,在服务端是可以监控到客户端通过ICustomizeInfoOutter接口发出的所有自定义信息的。
另外,关于同步调用服务端或同步调用其它客户端(Query方法)以及组广播信息(BroadcastInGroup)时,所发出的自定义信息也是如此,而且同步调用其它客户端时的返回信息也是经过服务器转发的,所以,也可以被监控到。
如果客户端之间开启了P2P通道,它们之间的信息将不再经过服务器中转,而是直接经过P2P通道传送,所以这时,服务器就不能监控到这样的信息了。难道就没有办法了吗?不,我们还有一招。对于那些必须要被监控到的信息,客户端可以采用TransferByServer方法进行发送,该方法会强制信息必须通过服务器中转,即使有P2P通道存在也是这样。所以,这里总结的规则是:如果在客户端之间传递的某个信息必须要被服务端监控到,那么,客户端就应该调用TransferByServer方法来发送该信息。
在服务端,我们可以预定ICustomizeController接口的InformationReceived事件,来截获客户端发出的所有自定义信息。
(1)当收到来自客户端的任何自定义信息时,将触发该事件。要特别注意的是,该事件的处理函数不能抛出异常,否则将导致后续消息处理流程中断。所以,最好在该事件的处理函数中catch所有的异常。
(2)该事件处理函数应尽快返回。因为服务端只有在所有的事件函数执行完毕后,才会继续后续的消息处理流程,所以该事件处理函数返回得越快越好。如果有些处理函数的业务逻辑复杂,比较费时,可以考虑使用异步的方式。
(3)ICustomizeOutter接口发出的所有自定义信息都包含了相同几个方面的内容:自定义信息的类型、自定义信息的数据、信息的接收者。ESPlus使用Information类来封装这些内容,并且增加了SourceID属性以记录发送者的UserID。
InformationReceived事件只有一个Information类型参数。
注意,如果自定义信息的接收者为服务端,则DestID属性的值是NetServer.SystemUserID(即 "_0")。
(4)当预定了InformationReceived事件后,我们可以根据InformationType来筛选那些我们感兴趣的要监控的自定义信息,并对它们做一些记录或其它业务处理。
有些系统不仅仅需要在服务端监控重要的自定义信息,它还可能有这样的需求:需要一个特殊的客户端,并且只有类似管理员这样的高级用户才能登录这个特殊的客户端,通过该客户端,管理员可以监控到其它普通客户端发送的自定义信息。我们称这个特殊的客户端为监控端。
在有了上面介绍的原理的基础上,实现监控端也相当容易。当服务端在处理ICustomizeController的InformationReceived事件时,将需要被监控的信息转发给在线的监控端就可以了。服务端转发信息给监控端仍然可以使用ICustomizeController的Send方法:
(1)Send方法的userID参数传入登录监控端的用户的ID。
(2)将监控到的要转发的信息(InformationReceived事件的参数,即上面提到的被封装成Information对象)通过序列化后,作为一个新的自定义信息,分别新的将信息类型和序列化结果传入Send方法的第二和第三个参数。
(3)在监控端处理服务器转发过来的被监控到的信息(可反序列化为Information对象)以实现监控的业务逻辑即可。
请注意,服务端通过预定ICustomizeController接口的InformationReceived事件,只能监控到客户端由ICustomizeOutter接口发出的自定义信息,而不能监控到其它命名空间下的Outter接口发送的消息(注意这里的用词是消息,“自定义信息”特用于ESPlus.Application.CustomizeInfo空间),比如客户端通过IBasicOutter接口发出的消息,在服务端是不会触发InformationReceived事件的,它们属于不同的命名空间,是相互独立的。
关于ESFramework的任何问题,欢迎联系我们:
电话:027-87638960
Q Q:372841921