在ESFramework 4.0 快速上手一文中,我们讲述了如何使用Rapid引擎可以快速地上手ESFramework开发,文中介绍了使用 ESPlus.Application.CustomizeInfo命名空间下的类可以发送和处理自定义消息,本文我们就通过一个简单的例子来深入讲解如何使用自定义消息?
例子的场景很简单:假设客户端登陆到服务器之后,要求请求加入某个组,服务端收到该请求后,处理该请求,并给客户端相应的回复 -- 是否加入成功,客户端收到回复后,即可作出相应的处理?
一.定义消息类型和消息协议Contract
这个场景涉及到两种类型的消息:请求加入组(客户端发给服务器),加入组的结果(服务器回复给客户端)?于是,我们可以定义这两个消息类型:
public static class InformationTypes { /// <summary> /// 请求加入组 Client =》 Server ?对应的消息体为 JoinGroupContract /// </summary> public const int JoinGroup = 1; /// <summary> /// 加入组的结果 Server =》 Client ?对应的消息体为 JoinGroupResultContract /// </summary> public const int JoinGroupResult = 2; }
另外,我们可以客户端发给服务器的请求以及服务器给客户端的回复分别用协议类JoinGroupContract和JoinGroupResultContract封装起来:
[Serializable] public class JoinGroupContract { public JoinGroupContract() { } public JoinGroupContract(string _groupID, string _groupPwd) { this.groupID = _groupID; this.groupPwd = _groupPwd; } #region GroupID private string groupID = ""; /// <summary> /// 请求加入组的ID /// </summary> public string GroupID { get { return groupID; } set { groupID = value; } } #endregion #region GroupPwd private string groupPwd = ""; /// <summary> /// 请求加入组的密码 /// </summary> public string GroupPwd { get { return groupPwd; } set { groupPwd = value; } } #endregion } [Serializable] public class JoinGroupResultContract { public JoinGroupResultContract(){} public JoinGroupResultContract(bool _succeed) { this.succeed = _succeed; } #region Succeed private bool succeed = true; /// <summary> /// 加入组是否成功 /// </summary> public bool Succeed { get { return succeed; } set { succeed = value; } } #endregion }
当然,这里的协议类非常简单,而对于我们实际的应用,协议类中封装很多的信息都是可以的?
二.客户端向服务器发送请求
好了,客户端在引擎初始化成功之后,就可以向服务器发送加入组G001的请求了:
//向服务器请求 加入G100组 JoinGroupContract JoinGroupContract = new JoinGroupContract("G100", "123456"); rapidPassiveEngine.CustomizeInfoOutter.Send(InformationTypes.JoinGroup, ESBasic.Helpers.SerializeHelper.SerializeObject(JoinGroupContract));
三.服务器处理请求,并发送回复给客户端
服务端通过实现ESPlus.Application.CustomizeInfo.Server.ICustomizeInfoBusinessHandler接口的HandleInformation方法来处理该请求:
private ICustomizeInfoController customizeInfoController = ......; //服务端处理消息 public void HandleInformation(string sourceUserID, int informationType, byte[] info) { if(informationType == InformationTypes.JoinGroup) { JoinGroupContract joinGroupContract = (JoinGroupContract)ESBasic.Helpers.SerializeHelper.DeserializeBytes(info, 0, info.Length); string groupID = joinGroupContract.GroupID; // ........ (逻辑处理) JoinGroupResultContract resContract = new JoinGroupResultContract(true) ;//同意加入 // 向用户发r回复消息 this.customizeInfoController.Send(sourceUserID, InformationTypes.JoinGroupResult, SerializeHelper.SerializeObject(resContract)); return; } }
四.客户端处理服务器的回复
接下来,客户端也可以通过实现ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoBusinessHandler接口的HandleInformationFromServer方法来处理服务器的回复:
//客户端处理消息 public void HandleInformationFromServer(int informationType, byte[] info) { if (informationType == InformationTypes.JoinGroupResult) { JoinGroupResultContract resContract = (JoinGroupResultContract)SerializeHelper.DeserializeBytes(info, 0, info.Length); if (resContract.Succeed) { //...... 加入成功了,呵呵 } return; } }
这个demo简单地演示了消息类型的定义?协议类的定义?以及客户端向服务器发送请求?服务器处理请求并回复客户端的一个完整的处理流程?通过自定义消息,我们可以在服务端与客户端之间实现非常复杂的协作?所以,哪怕是使用ESFramework的快速引擎,我们也可以做很多很复杂的事情了?
有一点要特别注意,那就是尽可能使消息的尺寸小,在相同的频率下,消息越小,通信的效率越高?在本文的demo中,我们采用的是.NET自带的二进制序列化器将协议对象转化为byte[],而使用这个序列化器,所得到的byte[]通常都非常大,而消息越大,将使得服务端与客户端通信的负担增大?所以,如果有自己更好更简洁的序列化方式,建议不要采用.NET自带的二进制序列化器?
版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明!