在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前demo的基础上添加使用ESFramework.SL开发的Silverlight客户端。这样一来,不仅Silverlight客户端之间可以相互通信,Silverlight客户端还可以跟winform客户端进行通信。如果不了解在Silverlight中如何使用ESFramework,可以先看看ESFramework 4.0 快速上手 -- 在Silverlight中使用ESFramework。
Silverlight客户端同样实现了以下功能并有所增强:
(1)客户端用户上下线时,通知其他在线用户。
(2)当客户端与服务端网络断开时,进行自动重连,当网络恢复后,重连成功。
(3)所有在线用户(包括Winform客户端)之间可以进行文字聊天。
(4)消息同步调用。(演示了三种类型的同步调用)
(5)重登陆模式。当同名的用户登陆时,会把前面的用户挤掉。
一.服务端
服务端直接使用ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)的实现,并且增加了服务器同步调用客户端的功能 -- 即服务端向某个在线客户端提交请求并返回客户端的回复信息。我们利用了服务端UI的“工具”菜单里面“自定义功能”,当点击这个菜单时,将默认向在线用户列表中的第一个用户发送同步调用请求。如图中第一个在线用户是aa01,那么点击“自定义功能”后,就由aa01来处理服务端的同步调用。
服务端同步调用客户端由ICustomizeInfoController.QueryClient()方法来实现。
/// <summary>
/// 询问在线客户端,并返回应答信息。如果目标用户不在线,或超时没有应答则将抛出Timeout异常。
/// </summary>
/// <param name="userID">接收并处理服务器询问的目标用户ID</param>
/// <param name="informationType">自定义请求信息的类型</param>
/// <param name="info">请求信息</param>
/// <returns>客户端给出的应答信息</returns>
byte[] QueryClient(string userID, int informationType, byte[] info);
二.客户端
1.客户端的MainPage类实现了ESFramework.SL.Application.Basic.IBasicBusinessHandler接口,以接收其他用户的上下线通知、被挤掉线通知、心跳超时通知等。
2.客户端的MainPage类还实现了ESFramework.SL.Application.CustomizeInfo.ICustomizeInfoBusinessHandler接口,以处理来自其它用户的聊天消息、来自服务端的同步调用、以及来自其它客户端的P2P同步调用等。
3.客户端的MainPage类还预定并处理了ESFramework.SL.Rapid.IRapidPassiveEngine的TcpPassiveEngine属性的与连接状态变化相关的事件,如连接断开、重连开始、重连成功/失败。
客户端启动登陆后,显示的主界面MainPage如下:
当有其他用户登陆时,会在“在线用户列表”中显示出来,点击选择用户ID,就可以与该用户聊天。UI右边上面是与所选择的用户的聊天历史记录,下面是发送消息的文本框。 从在线用户列表选择要对话的好友,然后在聊天输入框输入文本,最后点击“发送”按钮即可。程序通过ESFramework.SL.Application.CustomizeInfo.ICustomizeInfoOutter的Send方法发送消息给好友。
void Send(string targetUserID, int informationType, byte[] info);
好友掉线时,好友的名称会从好友列表中消失,如果正在与该好友聊天,则右边的历史记录会清空,“发送”按钮也不再可用。
如果我们在另一个地方再登陆一个aa01(演示重登陆),程序会先回调ESFramework.SL.Application.Basic.IBasicBusinessHandler的OnBeingPushedOut(),然后再触发TcpPassiveEngine的ConnectionInterrupted事件,通知当前的用户。
三、同步调用
这个demo里面演示了三种类型的同步调用:客户端与客户端之间的同步调用,客户端同步调用服务端,服务端同步调用客户端。
1.客户端同步调用服务端:这个在前一个Demo中演示过,在Sliverlight客户端中完全使用一样的模式。
2. 服务端同步调用客户端:这个在第一部分已经介绍,而客户端是通过实现ICustomizeInfoBusinessHandler接口的HandleQueryFromServer方法来处理来自服务端的同步调用的:
/// <summary>
/// 处理来自服务端的询问信息,并给出应答信息。(即处理服务端ICustomizeInfoController.QueryClient发出的请求)
/// </summary>
/// <param name="informationType">自定义信息类型</param>
/// <param name="info">二进制信息</param>
/// <returns>应答信息</returns>
byte[] HandleQueryFromServer(int informationType, byte[] info);
3. 客户端同步调用客户端:调用是由ICustomizeInfoOutter接口的CommitP2PRequest方法来发出的,
/// <summary>
/// 向在线目标用户提交请求信息,并返回应答信息。如果目标用户不在线,或超时没有应答则将抛出Timeout异常。
/// </summary>
/// <param name="targetUserID">接收并处理请求消息的目标用户ID</param>
/// <param name="requestInfoType">自定义请求信息的类型</param>
/// <param name="requestInfo">请求信息</param>
/// <returns>应答信息</returns>
byte[] CommitP2PRequest(string targetUserID, int requestInfoType, byte[] requestInfo);
目标客户端收到来自其他用户的同步调用请求后,会由ICustomizeInfoBusinessHandler接口的HandleP2PRequest方法来处理这个请求:
byte[] HandleP2PRequest(string sourceUserID, int requestInfoType, byte[] requestInfo);
四. 两种类型的客户端公用同一服务端
基于ESFramework Rapid引擎开发的winform客户端和silverlight客户端可以公用同一个服务端,甚至以后,ESFramework还可能支持基于C++/Flash/Java的客户端。下图是本文的Demo启动后,silverlight客户端和winform客户端用户之前的通信截图。
五.Demo源码下载
下载本文的Demo源码。注意,在运行基于Silverlight的客户端程序时,服务器上首先应该起到“Silverlight策略服务器”,可以从ESFramework 4.0 概述文末下载策略服务器。