在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活,心跳机制就产生了,运行机制就是客户端间隔一定时间往服务器发送一个数据包,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。总体的心跳设计机制围绕这个原则展开,我这里举例的都是实时性不高的游戏,实时性高的游戏,需要另外完善一些机制。
客户端需要考虑的情况:
1游戏中切到后台,接电话发微信等后,回到游戏。
2 wifi跟4G或者5G网络的切换。
3 wifi连接路由,但是路由上不了网。
4 某种情况下socketerror服务器主动断开。
5 游戏中长时间不操作息屏了。
以上几种情况,几乎都要触发自动重连机制。一般自动重连n次后失败,则弹出彻底断开游戏链接,回到登录界面.
判断网络情况都是一种状态,所以可以枚举下状态
None,
Wait,
Connected,
Disconnected,
玩家点击登录,状态为wait,经过验证服跟网关成功后设置为connected,完成登录,同时心跳组件开启,心跳组件假如约定,5秒一个包,服务器3分钟内没收到个心跳更新包,则认为客户端不存活了,网关加入一个预移除列表。
心跳组件设计,update中每隔5秒call一个包回来,如果发送失败了,则记录发送失败次数,连续3次发送失败,或者发送出现异常,则弹出断开链接,提示玩家已经与服务器失去链接。
刚上面所说情况,我们逐一进行分析,当网络进行切换的时候,wifi-移动来回切换,经常遇到,比如在客厅,用wifi,出个门拿快递,换了4G,此时网络检测到了变换,原先的session建立的socket将会断开了,此时玩家还在游戏内应该进行新的session生成并链接网关替换旧的session,成功后移除客户端旧的session,完成自动重连功能,当然在重连过程开始,应该把旧的session未发送的请求全部定位到新的session上,待新的session建立链接后再次发送,玩家几乎无感知,当静默重连N次后,还是无法链接,则提示玩家链接失败,回到登录界面。另外重连过程中,需要检测玩家是否在游戏内,网络状态是否为disconnect 或者wait,或者已经在链接中。
同理在通信过程中,tchannel有可能发生服务器主动reset 链接,也就是socket被重置了,发生了socketerror,此时应该在网络状态中设置为disconnect即可,心跳组件在发送过程中会判断这个状态情况,从而影响心跳,回到心跳的异常了。
另外一种情况,游戏切到后台,当打电话或者发微信的时候,游戏被切到后台,此时利用好客户端的OnApplicationFocus记录失去焦点时间,等回到游戏内再次记录一个时间,比如这个时间差超过30分钟,则直接弹出断开链接,如果非超过30分钟此时再次检测netstate,如果断开触发静默重连。
最好一种情况是息屏,有些手机手机息屏后会主动杀掉socket链接,比如ios12以下的手机,华为手机好像也会,此时屏幕再次打开,游戏内应该触发静默重连上去。重走静默重连。
玩家的数据发送或者请求可以做个发送队列,依次进行请求的发送,这样排查问题跟网络情况也非常容易,目前基本完全满足策划对网络这块弱网,断网,网络切换等各种不同情况的需求。