ET框架心跳包组件开发

网络游戏经常会发生(玩家断网、电脑死机、等)现象、这些会造成服务器里存在很多Session存在。

为什么Session会一直存在,不会自动销毁吗?因为服务器是不会知道这个Session是不是(玩家断网、电脑死机、等)现象。

断开网络连接需要4次握手才可以完成、但(玩家断网、电脑死机、等)现象是不会有4次握手的。

明白了这个问题,就需要做一个功能那就是每隔一段时间给服务器发送数据,表示我还在跟你连接,如果服务器里发现某个Session长时间没有发包了那就表示这个Session是无效的。

ET很强大,但没有提供这个心跳,需要自己开发一个这样的功能。

设计思路:

  • 心跳协议包(进行客户端跟服务端相互通信的数据包)
  • 心跳组件(ET是ECS框架也就是组件式、所以要开发出客户端和服务端的组件)

心跳协议包(服务端和客户端都需要):

需要在Opcode.cs里添加两个枚举、分别C2R_HeartBeat、R2C_HeartBeat

public enum Opcode: ushort

 

{

C2R_HeartBeat = 500,

R2C_HeartBeat = 501

}

需要在OuterMessage.cs文件里的添加两个类、分别C2R_HeartBeat、R2C_HeartBeat

QQ图片20180206170908

需要在OuterMessage.cs文件里的public partial class  ARequest {}上添加

ProtoInclude((int)Opcode.C2R_HeartBeat, typeof(C2R_HeartBeat))]

[BsonKnownTypes(typeof(C2R_HeartBeat))]

需要在OuterMessage.cs文件里的public partial class  AResponse {}上添加

[ProtoInclude((int)Opcode.R2C_HeartBeat, typeof(R2C_HeartBeat))]
[BsonKnownTypes(typeof(R2C_HeartBeat))]

2

服务端心跳组件:

Model项目下Component文件夹下创建HeartBeatComponent.cs文件并使用以下代码

 

[ObjectSystem]
public class HeartBeatSystem : ObjectSystem<HeartBeatComponent>, IUpdate { public void Update() { this.Get().Update(); } } /// <summary> /// Session心跳组件(需要挂载到Session上) /// </summary> public class HeartBeatComponent : Component { /// <summary> /// 更新间隔 /// </summary> public long UpdateInterval = 5; /// <summary> /// 超出时间 /// </summary> /// <remarks>如果跟客户端连接时间间隔大于在服务器上删除该Session</remarks> public long OutInterval = 10; /// <summary> /// 记录时间 /// </summary> private long _recordDeltaTime = 0; /// <summary> /// 当前Session连接时间 /// </summary> public long CurrentTime = 0; public void Update() { // 如果没有到达发包时间、直接返回 if (!((TimeHelper.ClientNowSeconds() – this._recordDeltaTime) > this.UpdateInterval) || CurrentTime == 0) return; // 记录当前时间 this._recordDeltaTime = TimeHelper.ClientNowSeconds(); if ((TimeHelper.ClientNowSeconds() – CurrentTime) > OutInterval) { // 移除Session Game.Scene.GetComponent<NetOuterComponent>().Remove(this.Parent.Id); Game.Scene.GetComponent<NetInnerComponent>().Remove(this.Parent.Id); Game.Scene.GetComponent<GateSessionKeyComponent>().Remove(this.Parent.Id); } } 

}

 

这段代码实现的功能是每隔一段时间检查当前Session连接时间是否超过OutInterval设定的时间,如果超过那就表示客户端可能是断线了。

那就需要把这个Session给销毁掉。

服务端挂载心跳组件:

需要挂载到网关服务器上。

添加心跳组件:session.AddComponent<HeartBeatComponent>().CurrentTime = TimeHelper.ClientNowSeconds();

在R2G_GetLoginKeyHandler.cs文件里挂载上心跳组件

3

CurrentTime是当前连接时间,服务端每次接收到客户端的心跳包都会把服务器时间更新到CurrentTime里。

有了CurrentTime的时间就可以判断客户端是否掉线。

Session是每个客户端的连接、我需要把心跳组件挂载到Session上,这样就能实时监测每个Session的状态,如果是断开的就把自己销毁掉。

服务端收发心跳包:

在Hotfix项目Handler文件夹下创建C2R_HeartBeatHandler.cs并使用以下代码


[MessageHandler(AppType.Gate)] public class C2R_HeartBeatHandler : AMRpcHandler<C2R_HeartBeat, R2C_HeartBeat> { protected override void Run(Session session, C2R_HeartBeat message, Action<R2C_HeartBeat> reply) { if (session.GetComponent<HeartBeatComponent>() != null) { session.GetComponent<HeartBeatComponent>().CurrentTime = TimeHelper.ClientNowSeconds(); } reply(new R2C_HeartBeat()); } } 

 

找到Session并更新下HeartBeatComponent的连接时间

客户端心跳组件:

的Component文件夹下创建HeartBeatComponent.cs文件,并使用以下代码

[ObjectSystem]
public class HeartBeatSystem : ObjectSystem<HeartBeatComponent>,IUpdate { public void Update() { this.Get().Update(); } } /// <summary> /// Session心跳组件(需要挂载到Session上) /// </summary> public class HeartBeatComponent: Component { /// <summary> /// 心跳包间隔 /// </summary> public float SendInterval = 2f; /// <summary> /// 记录时间 /// </summary> private float RecordDeltaTime = 0f; public async void Update() { // 如果还没有建立Session直接返回、或者没有到达发包时间 if (!((Time.time – this.RecordDeltaTime) > this.SendInterval)) return; // 记录当前时间 this.RecordDeltaTime = Time.time; // 开始发包 try { R2C_HeartBeat result = (R2C_HeartBeat) await this.GetParent<Session>().Call(new C2R_HeartBeat()); } catch { // 执行断线后的操作 Debug.Log(“断线了”); } } 

}

客户端挂载心跳组件:

Game.Scene.GetComponent<SessionComponent>().Session.AddComponent<HeartBeatComponent>();

这个组件挂载什么位置看个人而定,我是挂载到第一次跟服务器通讯的地方了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值