离线消息如何实现?-- ESFramework 4.0 快速上手(02)
在ESFramework 4.0 快速上手一文中,主要介绍了如何使用ESPlus.Rapid命名空间中的引擎来快速地构建基于TCP的网络通信系统,即使是使用ESPlus.Rapid来进行ESFramework快速开发,也还有很多可以介绍的内容,于是,我想再多写几篇文章来说明现实通信系统中的一些常见需求如何使用ESFramework快速实现。本文是为第一篇,介绍离线消息的原理和实现。
一.如何截获离线消息
阅读了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, byte[] info);
对于类似在线用户发给其他用户的P2P类型的消息,可以通过P2P通道发送,也可以通过服务器中转。当目标用户不在线时,P2P通道肯定是不存在的,所以消息一定是提交到服务器。服务器接收到要转发的P2P消息时,判断目标用户是否在线,如果在线,则直接转发;否则,框架会回调ESPlus.Application.CustomizeInfo.Server.ICustomizeInfoBusinessHandler接口的OnTransmitFailed方法:
/// <summary>
/// 当因为目标用户不在线而导致服务端转发自定义信息失败时,框架将调用此方法来通知应用程序。
/// </summary>
/// <param name="information">转发失败的信息</param>
void OnTransmitFailed(Information information);
我们只要实现ICustomizeInfoBusinessHandler接口的这个方法就可以监控到所有的离线消息了。
二.离线消息管理
截获到离线消息后,我们可能需要将其存到数据库,然后,等到目标用户上线的时候,再从数据库中提取属于该用户的离线消息发送给他即可。
首先,我们需要对离线消息做一个封装 -- OfflineMessage:
接下来,我们定义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(Information information)
{
OfflineMessage msg = new OfflineMessage(information.SourceID, information.DestID, information.InformationType, information.Content);
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)
{
this.customizeInfoController.Send(msg.DestUserID, msg.InformationType, msg.Information);
}
}
}
}
当用户上线时,会将属于他的离线消息按照时间的顺序一一发送给他。当然,你也可以将属于他的所有离线消息打成一个包,一次性发送也可以。如果是这样,你就需要再增加一条自定义的信息类型和相关的协议类了。
五.小结
从上面可以看出,基于ESFramework实现离线消息策略是相当简单的,最主要的焦点有两个:第一是可以通过实现ICustomizeInfoBusinessHandler接口来截获到所有的离线消息;第二是通过IUserManager的SomeOneConnected事件就能知道用户上线的时刻。
有的朋友可能会问离线文件又该怎么实现了?实际上也是同样的原理,只不过要多用到ESPlus.Application.FileTransfering命名空间下的一些类来完成文件的收发功能,这个等有时间的时候再来介绍。
本文只是实现离线消息的一个简单示例,在实际的应用中,可能需要做更多的工作来满足项目的具体需要,这里就不再一一赘述了。
离线消息如何实现?-- ESFramework 4.0 快速上手(02)的更多相关文章
- ESFramework 4.0 快速上手(01) -- Rapid引擎
(在阅读该文之前,请先阅读 ESFramework 4.0 概述 ,会对本文的理解更有帮助.) ESFramework/ESPlatform 4.0 的终极目标是为百万级的用户同时在线提供支持,因为强 ...
- 聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)
在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前d ...
- ESFramework 4.0 快速上手(06) -- Rapid引擎(续)
<ESFramework 4.0 快速上手>系列介绍的都是如何使用Rapid引擎(快速引擎) -- RapidServerEngine 和 RapidPassiveEngine.其实,大家 ...
- 如何使用自定义消息?--ESFramework 4.0 快速上手(04)
在ESFramework 4.0 快速上手一文中,我们讲述了如何使用Rapid引擎可以快速地上手ESFramework开发,文中介绍了使用ESPlus.Application.CustomizeInf ...
- 聊天系统Demo,增加文件传送功能(附源码)-- ESFramework 4.0 快速上手(14)
本文我们将介绍在ESFramework 4.0 快速上手(08) -- 入门Demo,一个简单的IM系统(附源码)的基础上,增加文件传送的功能.如果不了解如何使用ESFramework提供的文件传送功 ...
- 监控自定义信息 —— ESFramework 4.0 快速上手(10)
在ESFramework 4.0 进阶(02)-- 核心:消息处理的骨架流程一文中,我们介绍了通过挂接IMessageSpy到骨架流程,我们就可以监控到所有收发的消息.由于Rapid引擎已经为我们组装 ...
- 重登陆模式 --ESFramework 4.0 快速上手(07)
在ESFramework框架中基于TCP的服务端引擎(当然也包括Rapid引擎)都采用了这样一条规则:默认情况下,客户端与服务器成功建立TCP连接以后,服务端会从客户端发过来的第一条消息中取出消息头的 ...
- 文件传送,如此简单--ESFramework 4.0 快速上手(13)
在所有的通信系统中,文件传送是最常见也是最重要的功能之一,ESFramework对文件传送的强大支持也是其亮点之一,使用ESFramework可以非常轻松地实现与文件传送相关的所有需求.ESPlus. ...
- 使用紧凑的序列化器,数倍提升性能 —— ESFramework 4.0 快速上手(11)
在分布式通信系统中,网络传递的是二进制流,而内存中是我们基于对象模型构建的各种各样的对象,当我们需要将一个对象通过网络传递给另一个节点时,首先需要将其序列化为字节流,然后通过网络发送给目标节点,目标节 ...
随机推荐
- 诡异的数学,数字问题 - leetcode
134. Gas Station 那么这题包含两个问题: 1. 能否在环上绕一圈? 2. 如果能,这个起点在哪里? 第一个问题,很简单,我对diff数组做个加和就好了,leftGas = ∑diff[ ...
- Reprint: Serialization
Having just recently ran into some major serialization issues I’m going to list some of the errors a ...
- python 基础篇第一篇
本节内容 1.python介绍 2.发展史 3.python2和python3 4.安装 5.简单程序,hello world程序 6.变量 7.用户输入 8.模块初识 9..pyc是什么? 10.数 ...
- C++的第一天
第一次写博客,第一天的C++,从第一讲视屏中了解到了,类,对象,oop编程思想 1.类包括对象和对象的行为,对象具有静态连接(对象的名字)和动态链接(对象的行为),视屏中提到了多态性,应该是不同的类具 ...
- java中的反编译
使用JD-GUI工具 支持mac os 和 windows 地址为:http://jd.benow.ca
- LNA
low noise amplifier ,低噪声放大器. PA主要侧重输出功率,LNA侧重噪声系数,所以LNA用于前级,PA用作末级.
- Oracle新实例创建
http://blog.itpub.net/29519108/viewspace-1443918/ 刚开始创建时,千万别点容器数据库,不然后面新建用户时,用户名前得加C##. 常用命令: sqlplu ...
- iOSAPP添加启动页
如果你在开发过程中出现屏幕显示内容比例不正常或者显示不全的问题,你发现不是代码或者约束的问题,那么很可能是启动页没有添加或者添加不全的原因,下面配一张问题图片上下黑屏 添加启动页步骤如下图 (1) ( ...
- js便利关联数组 及数组定义方式 分类
"http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=& ...
- [阿当视频]WEB组件学习笔记
— 视频看完了,自定义事件还不懂,等完全懂了再更新并完成整篇案例 1. JS分层和组件的种类浏览器底层包括HTML CSS JS(DOM/BOM/Style/Canvas 2D/WebGl/SVG) ...