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

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

    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         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定义如下:

 1     public interface 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。
    为了能处理来自客户端的动态组请求/消息,我们先要能区分它,我们消息类型枚举中增加定义:

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>
    
/// IGroupMessage ActiveGroup消息的基础接口,所有的组消息协议都要实现此接口。
    
/// zhuweisky 2006.04.06
    
/// </summary>
    public interface IActiveGroupMessage
    {
        
string                   GroupName{get ;}
        ActiveGroupMessageType ActiveGroupMessageType{
get ;}
    }

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

    public interface IActiveGroupHelper
    {
        IActiveGroupMessage ParseGroupMessage(NetMessage msg) ;
    }

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

ActiveGroupMessageDealer

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

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

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

posted @ 2006-04-07 10:24  zhuweisky  阅读(2133)  评论(2编辑  收藏  举报