在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
) ;
//
同意加入
//
向用户发送回复消息
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自带的二进制序列化器。
ESFramework 4.0 概述 (文末包含最新版本的ESFramework4.0以及相关demo、帮助文档下载)
《ESFramework 4.0 快速上手》系列所有文章
《ESFramework 4.0 高级进阶》系列所有文章