ESFramework介绍之(19)―― 对动态组ActiveGr

系统 1524 0

什么是动态组?举个例子就清楚了。QQ支持多人在一个组中聊天的模式是群,这是一种静态组;而MSN中的动态的将多个人拉到一个组中来群聊,就是动态组。关于动态组,还有一个很好的例子,就是多人联网游戏,比如联网的星际。首先由发起者创建一个组(动态组),然后其它玩家加入进来开始游戏,游戏结束了,该动态组就销毁了。所以说,动态组是个“临时性的”,生命比较短暂;而静态组,通常被存储于永久介质(如数据库)中,即使这场游戏结束,这个组依然存在,如。

ESFramework对静态组的支持是“好友管理器”――IFriendManager(存在于ESFramework V0.1+),而对动态组的支持主要是ESFramework.Network.ActiveGroup(存在于ESFramework V0.2+)命名空间。

在服务器运行的过程中,可能需要创建成百上千的动态组,所有这些动态组需要被管理起来,这个管理者就是IActiveGroupManager。动态组管理器主要有以下职责:
(1)根据请求创建/销毁动态组。
(2)将某用户加入到某动态组。
(3)将某用户从动态组中移除。
(4)将组消息在指定的组内广播。
(5)查询所有动态组的消息。

根据上述职责描述,可以定义IActiveGroupManager接口:

1 public interface IActiveGroupManager
2 {
3 bool CreateGroup( string creator, string groupName); // 如果有同名的group存在、则返回false
4 bool DestroyGroup( string userID, string groupName); // 如果无权删除、则返回false
5
6 JoinGroupResultJoinGroup( string userID, string groupName);
7 void DropoutFromGroup( string userID, string groupName);
8 void BroadcastMessage( string sourceUserID, string destGroupName,NetMessagemsg); // 在目标组内广播消息
9
10 ICollectionGroups{ get ;}
11 bool CreatorOwner{ set ;} // 如果为true,表示只有创建者才有权DestroyGroup
12 IToClientSenderToClientSender{ set ;}
13 }
14
15 public enum JoinGroupResult
16 {
17 Succeed,GroupIsNotExist,MaxSized
18 }

CreatorOwner属性表明是否只有组的创建者才有权销毁组。ESFramework中IActiveGroupManager接口的参考实现是ActiveGroupManager。IActiveGroupManager管理的对象是动态组,那么动态组的定义了、它有哪些职责:
(1)管理组内所有用户,支持用户加入组、从组中撤出。
(2)维护组的最大容量。如果当前Size已经达到最大容量,则无法再加入用户
(3)当组为空时,触发GroupEmptied事件。应用可以处理该事件,比如从管理器中删除对应的组。
动态组接口IActiveGroup定义如下:

1 public interface IActiveGroup
2 {
3 string Creator{ get ;} // 创建者
4 string GroupName{ get ;}
5 int Count{ get ;}
6 int MaxSize{ get ; set ;}
7
8 IListUserList{ get ;}
9
10 bool AddUser( string userID); // 当达到MaxSize时,返回false
11 void RemoveUser( string userID);
12
13 event CbSimpleGroupEmptied;
14 }

ESFramework中IActiveGroup接口的参考实现是EsbActiveGroup。
为了能处理来自客户端的动态组请求/消息,我们先要能区分它,我们消息类型枚举中增加定义:

1 public enum ServiceType
2 {
3 Basic, // IBasicRequestDealer
4 Function,
5 P2PMessage, // 对于P2P消息,服务器仅仅转发,P2PMessageDealer
6 FriendRelation, // 如好友列表、好友资料等,FriendRelationDealer
7 GroupMessage , // 如多人联网游戏中的同步消息等
8 CustomServiceType // 自定义服务种类
9 }

接着,对于GroupMessage这个大类,我们需要进一步细分:

public enum ActiveGroupMessageType
{
Create,
// 需要回复-创建是否成功
Destroy, // 需要回复-销毁是否成功
Join, // 需要回复-加入是否成功
DropoutFromGroup, // 不需要回复
Broadcast // 如游戏同步消息,不需要回复
}

为了使ESFramework能一致的处理所有的GroupMessage,我们设定了IActiveGroupMessage接口,所有的GroupMessage都可以转换到这个接口:

/// <summary>
/// IGroupMessageActiveGroup消息的基础接口,所有的组消息协议都要实现此接口。
/// zhuweisky2006.04.06
/// </summary>
public interface IActiveGroupMessage
{
string GroupName{ get ;}
ActiveGroupMessageTypeActiveGroupMessageType{
get ;}
}

另外,我们需要一个帮手来实现这个转换:

public interface IActiveGroupHelper
{
IActiveGroupMessageParseGroupMessage(NetMessagemsg);
}

好了,一切就绪了,我们只差一个对应的消息处理器来处理所有的GroupMessage,这个消息处理器就是ActiveGroupMessageDealer,它借助于IActiveGroupManager实现了对所有GroupMessage的处理,下面给出它的实现源码:

ActiveGroupMessageDealer
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--> 1 public class ActiveGroupMessageDealer:IDataDealer
2 {
3 public ActiveGroupMessageDealer()
4 {
5 }
6
7 #region Property
8 #region ActiveGroupHelper
9 private IActiveGroupHelperactiveGroupHelper = null ;
10 public IActiveGroupHelperActiveGroupHelper
11 {
12 set
13 {
14 this .activeGroupHelper = value;
15 }
16 }
17 #endregion
18
19 #region ActiveGroupManager
20 private IActiveGroupManageractiveGroupManager = null ;
21 public IActiveGroupManagerActiveGroupManager
22 {
23 set
24 {
25 this .activeGroupManager = value;
26 }
27 }
28 #endregion
29 #endregion
30
31 #region IDataDealer成员
32
33 public NetMessageDealRequestMessage(NetMessagereqMsg)
34 {
35 IActiveGroupMessagegroupMsg = this .activeGroupHelper.ParseGroupMessage(reqMsg);
36 if (groupMsg == null )
37 {
38 return null ;
39 }
40
41 IMessageHeaderresHeader = (IMessageHeader)reqMsg.Header.Clone();
42
43 switch (groupMsg.ActiveGroupMessageType)
44 {
45 case ActiveGroupMessageType.Create:
46 {
47 bool suc = this .activeGroupManager.CreateGroup(reqMsg.Header.UserID,groupMsg.GroupName);
48 resHeader.MessageBodyLength = 0 ;
49 resHeader.Result = suc ? 1 :ServiceResultType.GroupIsExist;
50 return new NetMessage(resHeader, null );
51 }
52 case ActiveGroupMessageType.Destroy:
53 {
54 bool suc = this .activeGroupManager.DestroyGroup(reqMsg.Header.UserID,groupMsg.GroupName);
55 resHeader.MessageBodyLength = 0 ;
56 resHeader.Result = suc ? 1 :ServiceResultType.NoPermissionToDestroyGroup;
57 return new NetMessage(resHeader, null );
58 }
59 case ActiveGroupMessageType.Join:
60 {
61 JoinGroupResultresult = this .activeGroupManager.JoinGroup(reqMsg.Header.UserID,groupMsg.GroupName);
62 resHeader.MessageBodyLength = 0 ;
63 resHeader.Result = ActiveGroupMessageDealer.ConvertServiceResultType(result);
64 return new NetMessage(resHeader, null );
65 }
66 case ActiveGroupMessageType.DropoutFromGroup:
67 {
68 this .activeGroupManager.DropoutFromGroup(reqMsg.Header.UserID,groupMsg.GroupName);
69 return null ;
70 }
71 case ActiveGroupMessageType.Broadcast:
72 {
73 this .activeGroupManager.BroadcastMessage(reqMsg.Header.UserID,groupMsg.GroupName,reqMsg);
74 return null ;
75 }
76 default :
77 {
78 return null ;
79 }
80 }
81 }
82
83 #endregion
84
85 #region ConvertServiceResultType
86 public static int ConvertServiceResultType(JoinGroupResultresult)
87 {
88 switch (result)
89 {
90 case JoinGroupResult.GroupIsNotExist:
91 {
92 return ServiceResultType.GroupIsNotExist;
93 }
94 case JoinGroupResult.MaxSized:
95 {
96 return ServiceResultType.GroupSizeLimited;
97 }
98 case JoinGroupResult.Succeed:
99 {
100 return ServiceResultType.ServiceSucceed;
101 }
102 default :
103 {
104 return ServiceResultType.ServiceSucceed;
105 }
106 }
107 }
108 #endregion
109 }

最后,我们将ActiveGroupMessageDealer处理器添加到默认的处理器工厂EsbRequestDealerFactory中。(代码略)
说明一下,ActiveGroup的命名空间是ESFramework.Network.ActiveGroup,表明其与协议是无关的,即它可以用于Tcp协议,也可以用于Udp协议。
感谢关注!

上一篇文章: ESFramework介绍之(18)―― Tcp用户管理器组件

转到: ESFramework 可复用的通信框架(序)

ESFramework介绍之(19)―― 对动态组ActiveGroup的支持


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论