任务13:后端-注册登录需要创建的组件类与打开OuterMessageDispatcher分发注释
本节课开始前:我们来看服务端是怎么创建 Session的
public void OnAccept(AChannel channel) { Session session = ComponentFactory.CreateWithParent<Session, AChannel>(this, channel); this.sessions.Add(session.Id, session); session.Start(); }
目前还不需要太明白原理,先知道服务端只要收到消息或请求,他就会调用这个OnAccept方法,我们可以看到这里创建了一个Session,并且用这个session的id作为key,存到了sessions集合中。
ET是通过Channel (通信通道)实时同步消息的,一个信道是一个用户的实时连接,搭配一个session。Channel实时在同步,拿到消息后由session分发消息(有时候是直接返回给客户端,有时要转分发给Map、Gate),当然session也负责发起消息与请求。
因为Session是通信的核心类,需要建立一个Session的正确思路,所以上面交待了一下他的背景。
为了实现用户登录注册,我们前面讲了安装好MongoDB,在服务端项目中创建了数据相关的实体类AccountInfo,UserInfo,网关实体类:User,地图实体类:Gamer,Room。
本节课我们继续来做所需要的组件类。
网关组件 UserComponent,SessionUserComponent,SessionKeyComponent
UserComponent很简单,提供了Dictionary<long, User> idUsers来存放所有的User
还有Add,Get,Remove,GetAll几个增,减,获取某个User或全部User的方法。
UserComponent.cs
\Server\ET.Core\Landlords\Component\UserComponent.cs
using System.Collections.Generic; using System.Linq; namespace ETModel { /// <summary> /// 在线User对象管理组件 /// </summary> public class UserComponent : Component { private readonly Dictionary<long, User> idUsers = new Dictionary<long, User>(); /// <summary> /// 添加User对象 /// </summary> /// <param name="user"></param> public void Add(User user) { if(Get(user.UserID) == null) { this.idUsers.Add(user.UserID, user); } else { Log.Error("重复登录!"); } } /// <summary> /// 获取User对象 /// </summary> /// <param name="id"></param> /// <returns></returns> public User Get(long id) { this.idUsers.TryGetValue(id, out User gamer); return gamer; } /// <summary> /// 移除User对象 /// </summary> /// <param name="id"></param> public void Remove(long id) { this.idUsers.Remove(id); } /// <summary> /// User对象总数量 /// </summary> public int Count { get { return this.idUsers.Count; } } /// <summary> /// 获取所有User对象 /// </summary> /// <returns></returns> public User[] GetAll() { return this.idUsers.Values.ToArray(); } public override void Dispose() { if (this.IsDisposed) { return; } base.Dispose(); foreach (User user in this.idUsers.Values) { user.Dispose(); } } } }
SessionUserComponent.cs
\Server\ET.Core\Landlords\Component\SessionUserComponent.cs
也好理解,这个组件是Add到Session对象上的,就提供了
public User User { get; set; } 很明显就是把User与Seesion绑定起来,以供使用。
using System.Net; namespace ETModel { /// <summary> /// Gate服务器上 Session关联User对象组件 /// 用于Session断开时触发下线 /// </summary> public class SessionUserComponent : Component { //Gate服务器上 Session绑定的User对象 public User User { get; set; } } }
SessionKeyComponent.cs
\Server\ET.Core\Landlords\Component\SessionKeyComponent.cs
下节课我们就会讲到用户登录的实现过程,先到到网关gate请求登录,验证账号名密码后,就会到realm上获得一个sessionKey,这说明你是认证过的合法用户了,SessionKeyComponent就是用这个sessionKey作为key,UserID作为值存起来了,这样就能识别非法请求,一概不理或作处理。
using System.Collections.Generic; namespace ETModel { public class SessionKeyComponent : Component { private readonly Dictionary<long, long> sessionKey = new Dictionary<long, long>(); public void Add(long key, long userId) { this.sessionKey.Add(key, userId); this.TimeoutRemoveKey(key); } public long Get(long key) { long userId; this.sessionKey.TryGetValue(key, out userId); return userId; } public void Remove(long key) { this.sessionKey.Remove(key); } private async void TimeoutRemoveKey(long key) { await Game.Scene.GetComponent<TimerComponent>().WaitAsync(20000); this.sessionKey.Remove(key); } } }
Map上的组件 LandlordsComponent
本节作为了解,先知道他的存在,因为登录、注册还不用进入地图,所以先不详细介绍,暂时用不到。
realm组件 OnlineComponent
这个组件有一个 Dictionary<long, int> dictionary,用来存UserID和gateAppID,记录在线用户。
可以用这个组件添加的移除在线用户,获取用户的网关gateAppID。
\Server\ET.Core\Landlords\Component\OnlineComponent.cs
using System.Collections.Generic; namespace ETModel { /// <summary> /// 在线组件,用于记录在线玩家 无扩展 /// </summary> public class OnlineComponent : Component { /// <summary> /// 参数1:永久UserID 参数2:User对应Player所在的Gate的app编号 /// </summary> private readonly Dictionary<long, int> dictionary = new Dictionary<long, int>(); /// <summary> /// 添加在线玩家 参数1:永久Id 参数2:所在Gate的app编号 /// </summary> /// <param name="userId"></param> /// <param name="gateAppId"></param> public void Add(long userId, int gateAppId) { dictionary.Add(userId, gateAppId); } /// <summary> /// 获取在线玩家网关服务器ID /// </summary> /// <param name="userId"></param> /// <returns></returns> public int GetGateAppId(long userId) { int gateAppId; dictionary.TryGetValue(userId, out gateAppId); return gateAppId; } /// <summary> /// 移除在线玩家 /// </summary> /// <param name="userId"></param> public void Remove(long userId) { dictionary.Remove(userId); } } }
[很重要!]有了前面创建的实体与组件类,打开OuterMessageDispatcher类中的下图所示注释
\Server\Hotfix\Module\Message\OuterMessageDispatcher.cs
数据组件 DBProxyComponent
这个组件框架在ET.Core\Module\DB目录提供了,我们操作MongoDB就要用到,下节课的内容。
通过过去这两节课,我们就准备好了注册,登录功能需要的实体类与组件类了,我们只需要在下节课,通过实现前端的请求+后端对应请求的System、处理Handler,就能完成登录注册功能了,掌握并且完成好后,今后的网络通信功能都是类似的ECS结构。
随着功能增加,实操应用增加,你会越来越熟悉、灵活使用,并且前面不太理解的东西会得到印证变得比较理解。