什么是动态组?举个例子就清楚了。QQ支持多人在一个组中聊天的模式是群,这是一种静态组;而MSN中的动态的将多个人拉到一个组中来群聊,就是动态组。关于动态组,还有一个很好的例子,就是多人联网游戏,比如联网的星际。首先由发起者创建一个组(动态组),然后其它玩家加入进来开始游戏,游戏结束了,该动态组就销毁了。所以说,动态组是个“临时性的”,生命比较短暂;而静态组,通常被存储于永久介质(如数据库)中,即使这场游戏结束,这个组依然存在,如。
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 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定义如下:
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。
为了能处理来自客户端的动态组请求/消息,我们先要能区分它,我们消息类型枚举中增加定义:
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都可以转换到这个接口:
/// IGroupMessageActiveGroup消息的基础接口,所有的组消息协议都要实现此接口。
/// zhuweisky2006.04.06
/// </summary>
public interface IActiveGroupMessage
{
string GroupName{ get ;}
ActiveGroupMessageTypeActiveGroupMessageType{ get ;}
}
另外,我们需要一个帮手来实现这个转换:
{
IActiveGroupMessageParseGroupMessage(NetMessagemsg);
}
好了,一切就绪了,我们只差一个对应的消息处理器来处理所有的GroupMessage,这个消息处理器就是ActiveGroupMessageDealer,它借助于IActiveGroupManager实现了对所有GroupMessage的处理,下面给出它的实现源码:
最后,我们将ActiveGroupMessageDealer处理器添加到默认的处理器工厂EsbRequestDealerFactory中。(代码略)
说明一下,ActiveGroup的命名空间是ESFramework.Network.ActiveGroup,表明其与协议是无关的,即它可以用于Tcp协议,也可以用于Udp协议。
感谢关注!
上一篇文章:
ESFramework介绍之(18)―― Tcp用户管理器组件
转到:
ESFramework 可复用的通信框架(序)