监控自定义信息 —— ESFramework 4.0 快速上手(10)

      在ESFramework 4.0 进阶(02)-- 核心:消息处理的骨架流程一文中,我们介绍了通过挂接IMessageSpy到骨架流程,我们就可以监控到所有收发的消息。由于Rapid引擎已经为我们组装好了默认的骨架流程,如果使用Rapid引擎,我们就无法插入自定义的IMessageSpy。不过没关系,使用Rapid引擎的我们同样可以在服务端监控到客户端发出的所有自定义信息

 

一.深入ICustomizeInfoOutter接口

  我们已经非常熟悉ICustomizeInfoOutter接口了,客户端要发送任何自定义的信息,都是通过该接口来进行的。

    public interface ICustomizeInfoOutter :IOutter
    {
        /// <summary>
        /// 向服务器发送二进制信息。
        /// </summary>
        void Send(int informationType, byte[] info);

        /// <summary>
        /// 向服务器提交请求信息,并返回服务器的应答信息。如果超时没有应答则将抛出Timeout异常。
        /// </summary>      
        /// <param name="informationType">自定义请求信息的类型</param>
        byte[] CommitRequest(int informationType, byte[] info);

        /// <summary>
        /// 向在线目标用户提交请求信息,并返回应答信息。如果目标用户不在线,或超时没有应答则将抛出Timeout异常。
        /// </summary>      
        byte[] CommitP2PRequest(string targetUserID, int informationType, byte[] info);

        /// <summary>
        /// 向在线用户targetUserID发送二进制信息。如果目标用户不在线,则服务端会调用ICustomizeInfoBusinessHandler.OnTransmitFailed方法来通知应用程序。
        /// </summary>
        void Send(string targetUserID, int informationType, byte[] info);      

        /// <summary>
        /// 向目标组内所有在线用户广播二进制信息。(服务端采用Post)
        /// </summary>
        void BroadcastInGroup(string groupID, int informationType, byte[] info);
    }

      该接口的所有方法可以分为两类:一类方法是接收自定义信息的最终用户是服务端;另一类是接收自定义信息的最终用户是其他在线用户。无论是哪种情况,信息都会到达服务端,或由服务端处理、或经服务端转发。(如果客户端之间开启了P2P通道,则另当别论。)所以,在服务端是可以监控到客户端通过ICustomizeInfoOutter接口发出的所有自定义信息的。

      另外,关于同步调用服务端(CommitRequest方法)或同步调用其它客户端(CommitP2PRequest),所发出的自定义信息也是如此,而且同步调用其它客户端时的返回信息也是经过服务器转发的,所以,也可以被监控到。

 

二.截获自定义信息

      在服务端,我们可以预定ICustomizeInfoController接口的InformationReceived事件,来截获客户端发出的所有自定义信息。

   event CbGeneric<Information> InformationReceived;

(1)当收到来自客户端的任何自定义信息时,将触发该事件。要特别注意的是,该事件的处理函数不能抛出异常,否则将导致后续消息处理流程中断。所以,最好在该事件的处理函数中catch所有的异常。

(2)该事件处理函数应尽快返回。因为服务端只有在所有的事件函数执行完毕后,才会继续后续的消息处理流程,所以该事件处理函数返回得越快越好。如果有些处理函数的业务逻辑复杂,比较费时,可以考虑使用异步的方式。

(3)ICustomizeInfoOutter接口发出的所有自定义信息都包含了相同几个方面的内容:自定义信息的类型、自定义信息的数据、信息的接收者。ESPlus使用Information类来封装这些内容,并且增加了SourceID属性以记录发送者的UserID。InformationReceived事件只有一个Information类型参数。

    public class Information
    {
        #region SourceID
        private string sourceID = "";
        /// <summary>
        /// 信息的发送者。可以为UserID或者NetServer.SystemUserID。
        /// </summary>
        public string SourceID
        {
            get { return sourceID; }
            set { sourceID = value; }
        } 
        #endregion

        #region DestID
        private string destID = "";
        /// <summary>
        /// 信息的接收者。可以为UserID或者NetServer.SystemUserID或GroupID(广播消息)。
        /// </summary>
        public string DestID
        {
            get { return destID; }
            set { destID = value; }
        } 
        #endregion

        #region InformationType
        private int informationType = 0;
        /// <summary>
        /// 自定义信息类型
        /// </summary>
        public int InformationType
        {
            get { return informationType; }
            set { informationType = value; }
        } 
        #endregion

        #region Content
        private byte[] content = null;
        /// <summary>
        /// 信息的内容
        /// </summary>
        public byte[] Content
        {
            get { return content; }
            set { content = value; }
        } 
        #endregion
    }

      注意,如果自定义信息的接收者为服务端,则DestID属性的值是NetServer.SystemUserID(即 "_0")。

(4)当预定了InformationReceived事件后,我们可以根据InformationType来筛选那些我们感兴趣的自定义信息,并对它们做一些记录或其它业务处理。

 

三.更多说明

      服务端通过预定ICustomizeInfoController接口的InformationReceived事件,只能监控到客户端由ICustomizeInfoOutter接口发出的自定义信息,而不能监控到其它命名空间下的Outter接口发送的消息(注意这里的用词是消息,“自定义信息”特用于ESPlus.Application.CustomizeInfo空间),比如客户端通过IBasicOutter接口发出的消息,在服务端是不会触发InformationReceived事件的,它们属于不同的命名空间,是相互独立的。

      服务端如果要得到更多的通知,比如用户上下线,就可以通过预定IUserManager接口的相关事件来做到。

      如果,你所用的版本的ICustomizeInfoController接口没有InformationReceived事件,请到ESFramework 4.0 概述文末下载最新版本。

 

ESFramework 4.0 概述

《ESFramework 4.0 快速上手》系列所有文章

《ESFramework 4.0 高级进阶》系列所有文章

 

 

时间: 2024-11-09 00:51:04

监控自定义信息 —— ESFramework 4.0 快速上手(10)的相关文章

离线消息如何实现?-- ESFramework 4.0 快速上手(02)

在ESFramework 4.0 快速上手一文中,主要介绍了如何使用ESPlus.Rapid命名空间中的引擎来快速地构建基于TCP的网络通信系统,即使是使用ESPlus.Rapid来进行ESFramework快速开发,也还有很多可以介绍的内容,于是,我想再多写几篇文章来说明现实通信系统中的一些常见需求如何使用ESFramework快速实现.本文是为第一篇,介绍离线消息的原理和实现.   一.如何截获离线消息 阅读了ESFramework 4.0 快速上手朋友都知道,一个在线用户给另一个用户发送文

ESFramework 4.0 快速上手(01) -- Rapid引擎

(在阅读该文之前,请先阅读 ESFramework 4.0 概述 ,会对本文的理解更有帮助.) ESFramework/ESPlatform 4.0 的终极目标是为百万级的用户同时在线提供支持,因为强大,所以使用也较为复杂,配置也较多.但是如果我们的应用只是一个中小型的通信应用(同时在线5000人以下),直接使用ESPlatform就有点显得杀鸡用牛刀了.ESPlus.Rapid提供了一种快速的方式,来解决类似中小型的通信应用,以最简洁的方式来使用ESFramework. 使用ESPlus.Ra

ESFramework 4.0 快速上手(06) -- Rapid引擎(续)

<ESFramework 4.0 快速上手>系列介绍的都是如何使用Rapid引擎(快速引擎) -- RapidServerEngine 和 RapidPassiveEngine.其实,大家可以将这两个引擎看作是两个壳,内部包装的才是真正的ESFramework的网络引擎, ESFramework支持很多种网络引擎(客户端/服务端.二进制协议/文本协议.TCP/UDP),而RapidServerEngine和RapidPassiveEngine采用的是基于TCP和二进制协议的服务端引擎和客户端引

聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)

      在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前demo的基础上添加使用ESFramework.SL开发的Silverlight客户端.这样一来,不仅Silverlight客户端之间可以相互通信,Silverlight客户端还可以跟winform客户端进行通信.如果不了解在Silverlight中如何使用ESFramework,可以先看

使用紧凑的序列化器,数倍提升性能 —— ESFramework 4.0 快速上手(11)

在分布式通信系统中,网络传递的是二进制流,而内存中是我们基于对象模型构建的各种各样的对象,当我们需要将一个对象通过网络传递给另一个节点时,首先需要将其序列化为字节流,然后通过网络发送给目标节点,目标节点接收后,再反序列化为对象实例.在ESFramework体系中,也是遵循同样的规则.       ESFramework称这些需要经过网络传递的对象称之为协议类(Contract),协议类通常只是一个简单的数据结构封装,用于保存状态的一个哑类(不包含任何方法,从object继承的除外),有点类似于与

客户端登录验证 -- ESFramework 4.0 快速上手(15)

      在之前版本的Rapid引擎中,是没有提供客户端登陆验证的机制的,如果要验证用户的帐号密码信息,我们只有自己手动通过自定义信息来实现.在2011.04.25发布的新版本中,客户端Rapid引擎,则内置了在初始化时验证用户的帐号密码的功能,这使得登录验证变得更加简单.   一. ESPlus.Application.Basic 空间的支持       为了实现验证用户账号密码的功能,ESPlus.Application.Basic 命名空间增加了几个基础设施. (1)ESPlus.App

重登陆模式 --ESFramework 4.0 快速上手(07)

在ESFramework框架中基于TCP的服务端引擎(当然也包括Rapid引擎)都采用了这样一条规则:默认情况下,客户端与服务器成功建立TCP连接以后,服务端会从客户端发过来的第一条消息中取出消息头的UserID属性的值,并将其与对应的TCP连接绑定起来.这样,服务端就知道每一个TCP连接所对应的用户UserID,而当我们要求服务端向某个客户端发送消息时,服务端就知道通过哪个TCP连接进行发送了.TCP连接与UserID是一一对应的,一个TCP连接只能对应一个UserID,同样的,一个UserI

异常日志—— ESFramework 4.0 快速上手(03)

   ESFramework框架(包括ESPlus.ESPlatform)实现时就内置了相对完整的日志功能,几乎所有的异常(Exception)和错误信息都会被记录到日志.通过查看日志记录,我们可以了解到程序在运行的过程中出现了哪些非正常的状况,并且,详细的日志记录可以帮我们迅速定位问题,并解决问题.(关于我对日志记录的更多认识,可以参看我的博文我的架构经验小结(五)-- 日志记录 )   一.IAgileLogger接口     首先,ESFramework框架使用ESBasic.Logger

判定生死的心跳机制 --ESFramework 4.0 快速上手(07)

      在Internet上采用TCP进行通信的系统,都会遇到一个令人头疼的问题,就是"掉线".而"TCP掉线"这个问题远比我们通常所能想象的要复杂的多 -- 网络拓扑纷繁复杂.而从始节点A到终节点B之间可能要经过N多的交换机.路由器.防火墙等等硬件设备,每个硬件设备的相关设定也不统一,再加上网络中可能出现的拥塞.延迟等,使得我们在编程时,处理掉线也非常棘手.   一.从程序的角度看待TCP掉线       TCP掉线的原因可能多种多样.不一而足,比如,客人的电