文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>ESFramework 4.0 快速上手 -- 离线消息如何实现?

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

时间:2011-02-25  来源:zhuweisky

 

一.如何截获离线消息  

  阅读了ESFramework 4.0 快速上手朋友都知道,一个在线用户给另一个用户发送文本信息或二进制信息采用的是ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoOutter接口的Send方法,如发送文本信息:

        /// <summary>
        /// 向在线用户targetUserID发送文本信息。如果目标用户不在线,则服务端会调用ICustomizeInfoBusinessHandler.OnTransmitFailed方法来通知应用程序。
        /// </summary>
        /// <param name="targetUserID">接收消息的目标用户ID</param>
        /// <param name="informationType">自定义信息类型</param>
        /// <param name="info">文本信息</param>      
        void Send(string targetUserID, int informationType, string info);       

  对于类似在线用户发给其他用户的P2P类型的消息,可以通过P2P通道发送,也可以通过服务器中转。当目标用户不在线时,P2P通道肯定是不存在的,所以消息一定是提交到服务器。服务器接收到要转发的P2P消息时,判断目标用户是否在线,如果在线,则直接转发;否则,框架会回调ESPlus.Application.CustomizeInfo.Server.ICustomizeInfoBusinessHandler接口的OnTransmitFailed方法:

        /// <summary>
        /// 当因为目标用户不在线而导致服务端转发文本信息失败时,框架将调用此方法来通知应用程序。
        /// </summary>
        /// <param name="sourceUserID">发送信息的用户ID</param>
        /// <param name="destUserID">目标用户ID</param>
        /// <param name="informationType">自定义信息类型</param>
        /// <param name="info">文本信息</param>
        void OnTransmitFailed(string sourceUserID, string destUserID, int informationType, string info);

  我们只要实现ICustomizeInfoBusinessHandler接口的这个方法就可以监控到所有的离线消息了。

 

二.离线消息管理

  截获到离线消息后,我们可能需要将其存到数据库,然后,等到目标用户上线的时候,再从数据库中提取属于该用户的离线消息发送给他即可。

  首先,我们需要对离线消息做一个封装 -- OfflineMessage:

View Code     [Serializable]
    public class OfflineMessage
    {
        #region Ctor
        public OfflineMessage() { }
        public OfflineMessage(string _sourceUserID, string _destUserID, int _informationType, object info)
        {
            this.sourceUserID = _sourceUserID;
            this.destUserID = _destUserID;
            this.informationType = _informationType;
            this.information = info;
        } 
        #endregion

        #region SourceUserID
        private string sourceUserID = "";
        /// <summary>
        /// 发送离线消息的用户ID。
        /// </summary>
        public string SourceUserID
        {
            get { return sourceUserID; }
            set { sourceUserID = value; }
        } 
        #endregion

        #region DestUserID
        private string destUserID = "";
        /// <summary>
        /// 接收离线消息的用户ID。
        /// </summary>
        public string DestUserID
        {
            get { return destUserID; }
            set { destUserID = value; }
        } 
        #endregion

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

        #region Information
        private object information;
        /// <summary>
        /// 信息内容,可以是string或byte[]
        /// </summary>
        public object Information
        {
            get { return information; }
            set { information = value; }
        } 
        #endregion      
   
        #region Time
        private DateTime time = DateTime.Now;
        /// <summary>
        /// 服务器接收到要转发离线消息的时间。
        /// </summary>
        public DateTime Time
        {
            get { return time; }
            set { time = value; }
        } 
        #endregion
    }

  接下来,我们定义IOfflineMessageManager接口,用于管理离线消息:

    /// <summary>
    /// 离线消息管理器。
    /// </summary>
    public interface IOfflineMessageManager
    {
        /// <summary>
        /// 存储离线消息。
        /// </summary>       
        /// <param name="msg">要存储的离线消息</param>
        void Store(OfflineMessage msg);

        /// <summary>
        /// 提取目标用户的所有离线消息。
        /// </summary>       
        /// <param name="destUserID">接收离线消息用户的ID</param>
        /// <returns>属于目标用户的离线消息列表,按时间升序排列</returns>
        List<OfflineMessage> Pickup(string destUserID);
    }

  实现这个接口,我们便可以将离线消息存储到数据库或文本或网络等等,然后等到需要时再次从中提取。

 

三.存储离线消息

  有了IOfflineMessageManager接口,我们便可以实现ICustomizeInfoBusinessHandler接口的OnTransmitFailed方法了:

        private IOfflineMessageManager offlineMessageManager = ......;
        public void OnTransmitFailed(string sourceUserID, string destUserID, int informationType, string info)
        {
            OfflineMessage msg = new OfflineMessage(sourceUserID, destUserID, informationType, info);
            this.offlineMessageManager.Store(msg);
        }

  我们也许并不需要将所有的离线消息都存储起来,有些不重要的离线消息可以丢弃,而只保存那些我们关心的消息。这只需要在存储消息之前加一个条件判断进行过滤即可。

 

四.提取并发送离线消息

  我们已经知道,可以通过IUserManager的SomeOneConnected事件来得知某个用户上线了,于是,我们可以在该事件处理函数中,提取属于该用户的离线消息并发送给他。我们通过类似下面的代码来做到这一点。

    public class OfflineMessageBridge
    {
        #region UserManager
        private IUserManager userManager;
        public IUserManager UserManager
        {
            set { userManager = value; }
        } 
        #endregion

        #region OfflineMessageManager
        private IOfflineMessageManager offlineMessageManager;
        public IOfflineMessageManager OfflineMessageManager
        {
            set { offlineMessageManager = value; }
        } 
        #endregion

        #region CustomizeInfoController
        private ICustomizeInfoController customizeInfoController;
        public ICustomizeInfoController CustomizeInfoController
        {
            set { customizeInfoController = value; }
        } 
        #endregion

        public void Initialize()
        {
            this.userManager.SomeOneConnected += new CbGeneric<ESFramework.Server.UserManagement.UserData>(userManager_SomeOneConnected);
        }           

        void userManager_SomeOneConnected(ESFramework.Server.UserManagement.UserData userData)
        {
            List<OfflineMessage> list = this.offlineMessageManager.Pickup(userData.UserID);
            if (list != null && list.Count > 0)
            {
                foreach (OfflineMessage msg in list)
                {
                    if (msg.Information is string)
                    {
                        this.customizeInfoController.Send(msg.DestUserID, msg.InformationType, (string)msg.Information);
                    }
                    else
                    {
                        this.customizeInfoController.Send(msg.DestUserID, msg.InformationType, (byte[])msg.Information);
                    }

                }
            }
        }
    }

  当用户上线时,会将属于他的离线消息按照时间的顺序一一发送给他。当然,你也可以将属于他的所有离线消息打成一个包,一次性发送也可以。如果是这样,你就需要再增加一条自定义的信息类型和相关的协议类了。

 

五.小结

  从上面可以看出,基于ESFramework实现离线消息策略是相当简单的,最主要的焦点有两个:第一是可以通过实现ICustomizeInfoBusinessHandler接口来截获到所有的离线消息;第二是通过IUserManager的SomeOneConnected事件就能知道用户上线的时刻。

  有的朋友可能会问离线文件又该怎么实现了?实际上也是同样的原理,只不过要多用到ESPlus.Application.FileTransfering命名空间下的一些类来完成文件的收发功能,这个等有时间的时候再来介绍。

  本文只是实现离线消息的一个简单示例,在实际的应用中,可能需要做更多的工作来满足项目的具体需要,这里就不再一一赘述了。

 

注:可以到ESFramework 4.0 概述 文末下载最新版本的ESFramework以及相关帮助文档。

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载