ESFramework介绍之(19)―― 对动态组ActiveGroup的支持
什么是动态组?举个例子就清楚了。QQ支持多人在一个组中聊天的模式是群,这是一种静态组;而MSN中的动态的将多个人拉到一个组中来群聊,就是动态组。关于动态组,还有一个很好的例子,就是多人联网游戏,比如联网的星际。首先由发起者创建一个组(动态组),然后其它玩家加入进来开始游戏,游戏结束了,该动态组就销毁了。所以说,动态组是个“临时性的”,生命比较短暂;而静态组,通常被存储于永久介质(如数据库)中,即使这场游戏结束,这个组依然存在,如QQ群。
ESFramework对静态组的支持是“好友管理器”――IFriendManager(存在于ESFramework V0.1+),而对动态组的支持主要是ESFramework.Network.ActiveGroup(存在于ESFramework V0.2+)命名空间。
在服务器运行的过程中,可能需要创建成百上千的动态组,所有这些动态组需要被管理起来,这个管理者就是IActiveGroupManager。动态组管理器主要有以下职责:
(1) 根据请求创建/销毁动态组。
(2) 将某用户加入到某动态组。
(3) 将某用户从动态组中移除。
(4) 将组消息在指定的组内广播。
(5) 查询所有动态组的消息。
根据上述职责描述,可以定义IActiveGroupManager接口:
2 {
3 bool CreateGroup(string creator ,string groupName) ; //如果有同名的group存在、则返回false
4 bool DestroyGroup(string userID ,string groupName) ; //如果无权删除、则返回false
5
6 JoinGroupResult JoinGroup(string userID ,string groupName) ;
7 void DropoutFromGroup(string userID ,string groupName);
8 void BroadcastMessage(string sourceUserID ,string destGroupName ,NetMessage msg) ;//在目标组内广播消息
9
10 ICollection Groups{get ;}
11 bool CreatorOwner{set ;} //如果为true,表示只有创建者才有权DestroyGroup
12 IToClientSender ToClientSender{set ;}
13 }
14
15 public enum JoinGroupResult
16 {
17 Succeed ,GroupIsNotExist ,MaxSized
18 }
CreatorOwner属性表明是否只有组的创建者才有权销毁组。ESFramework中IActiveGroupManager接口的参考实现是ActiveGroupManager。IActiveGroupManager管理的对象是动态组,那么动态组的定义了、它有哪些职责:
(1) 管理组内所有用户,支持用户加入组、从组中撤出。
(2) 维护组的最大容量。如果当前Size已经达到最大容量,则无法再加入用户
(3) 当组为空时,触发GroupEmptied事件。应用可以处理该事件,比如从管理器中删除对应的组。
动态组接口IActiveGroup定义如下:
2 {
3 string Creator{get ;} //创建者
4 string GroupName{get ;}
5 int Count{get ;}
6 int MaxSize{get ;set ;}
7
8 IList UserList{get ;}
9
10 bool AddUser(string userID) ; //当达到MaxSize时,返回false
11 void RemoveUser(string userID) ;
12
13 event CbSimple GroupEmptied ;
14 }
ESFramework中IActiveGroup接口的参考实现是EsbActiveGroup。
为了能处理来自客户端的动态组请求/消息,我们先要能区分它,我们消息类型枚举中增加定义:
2 {
3 Basic , //IBasicRequestDealer
4 Function ,
5 P2PMessage , //对于P2P消息,服务器仅仅转发,P2PMessageDealer
6 FriendRelation , //如好友列表、好友资料等 ,FriendRelationDealer
7 GroupMessage , //如多人联网游戏中的同步消息等
8 CustomServiceType //自定义服务种类
9 }
接着,对于GroupMessage这个大类,我们需要进一步细分:
{
Create , //需要回复-创建是否成功
Destroy ,//需要回复-销毁是否成功
Join , //需要回复-加入是否成功
DropoutFromGroup ,//不需要回复
Broadcast //如游戏同步消息 ,不需要回复
}
为了使ESFramework能一致的处理所有的GroupMessage,我们设定了IActiveGroupMessage接口,所有的GroupMessage都可以转换到这个接口:
/// IGroupMessage ActiveGroup消息的基础接口,所有的组消息协议都要实现此接口。
/// zhuweisky 2006.04.06
/// </summary>
public interface IActiveGroupMessage
{
string GroupName{get ;}
ActiveGroupMessageType ActiveGroupMessageType{get ;}
}
另外,我们需要一个帮手来实现这个转换:
{
IActiveGroupMessage ParseGroupMessage(NetMessage msg) ;
}
好了,一切就绪了,我们只差一个对应的消息处理器来处理所有的GroupMessage,这个消息处理器就是ActiveGroupMessageDealer,它借助于IActiveGroupManager实现了对所有GroupMessage的处理,下面给出它的实现源码:
![](/Images/OutliningIndicators/ContractedBlock.gif)
最后,我们将ActiveGroupMessageDealer处理器添加到默认的处理器工厂EsbRequestDealerFactory中。(代码略)
说明一下,ActiveGroup的命名空间是ESFramework.Network.ActiveGroup,表明其与协议是无关的,即它可以用于Tcp协议,也可以用于Udp协议。
感谢关注!
上一篇文章:ESFramework介绍之(18)―― Tcp用户管理器组件
转到 :ESFramework 可复用的通信框架(序)