1、弱网络下的断线重连   玩家在游戏过程中,所处的网络环境是复杂多变的,可能是wifi的网络不稳定,或处在3G甚至2G的环境下等。在这些情况下,网络游戏会由于网络或包量等原因而出现延迟,拉拽,甚至掉线等问题。对于这些问题,一方面要对程序的包量和通信进行优化,从根本上减缓网络压力。另一方面,在出现网络异常的时候,保证玩家能重新连接到服务器并继续游戏,并且体验良好。   网络的“弱”主要体现在延迟和丢包率大两方面,而这两方面都会影响游戏的体验。我们在市区低速移动的网络情况下(丢包率10%, 平均延迟890ms)测试,并对此情况下进行分析优化,达到了玩家能够顺利游戏的体验。   由断线或网络异常性质决定,基本上都是首先由客户端感知,因此断线重连的机制主要是由客户端来进行发起。   下面我主要从客户端方向就断线重连触发的条件,如何重连,以及重连后的后续处理三个方面来阐述,最后简略分析一下对我们游戏客户端容易掉线的一些思考。 

2、判断重连条件   在弱网络条件下,我们根据网络状况的不同,有两种情况触发断线重连。

  网络条件异常
    在弱网络情况下,网络会显式的抛出一些异常,大部分情况下是NetworkException,少部分情况是Timeout(当然还有连接关闭等等其他异常,就不一一赘述)。在这种显式抛出异常的情况下,就说明网络已经无法顺利的和服务器进行连接,在这些消息类型中,对于客户端断网或网络波动导致的原因,客户端这边就会触发断线重连流程。

2    心跳包触发以及触发时间的确定
    上一种情况的触发条件是客户端手机本身断网或网络发生异常的情况的触发,但实际情况中,还有可能发生客户端网络并未断开,也并没有异常抛出,但是却出现客户端和服务器无法正常进行收发消息的情况。
  这种情况一方面原因是中间链路的连接异常,另一方面也会由于延迟过高或丢包导致的TCP重发造成的延迟过大,影响到服务器和客户端之间正常的收发消息。

在  市区低速移动的网络的模拟测试中,我们收集到的最大心跳包延迟是10s左右,也就是说,在此“弱”网络情况下,网络延迟峰值大概有10s以上。因此,我们对心跳包在一定时间内如果没有收到返回包的情况下也认为是一种掉线情况,会触发断线重连处理,目前在大厅设置的触发时间是30s,战斗中触发的时间是20s。

游戏切出
  有一种情况是由于客户端切出游戏,或者中间接到电话等导致游戏暂停等情况,在一定时间后服务器会主动断开和客户端的连接,客户端也需要主动触发重连。

3、断线重连的大致流程图
  断线重连收到网络异常消息阶段处理流程:




  断线重连结果处理阶段:



4、对流程图的补充说明
  1)在重连过程中,如果收到客户端主动断开的消息,会屏蔽所有重连行为
  2)由于在收到NetworkException的时候无法保证网络状态,如果此时网络已经连接上,会无法触发后续重连过程,所以会在NetworkException的时候double check一下是否连接到网络。


5、关于状态机:

断线重连并不是一个瞬间操作,而是一个过程。在整个断线重连的过程中,存在着一个个阶段,也就对应一个个的状态。初步来说,主要分为以下几个阶段。
A. Start:网络正常状态,简称S
B. Wait:网络已经断开,等待网络恢复,简称W
C. Reconnect:重新连接状态,简称R
D. End: 重新连接失败,简称E
  状态转换图见下:

   

6、重连后的相关处理
  在程序断线重连的过程中除非重连失败,否则最理想的情况是希望玩家在断线前后无感知,可以流畅的继续游戏而不受到断线的影响。
1) 对于大厅的后续处理
A.拉取相关属性和物品。再重新连接后,由于在断开过程中可能会有相关数据的变化,会拉取人物相关属性和物品
B.重发断线前的相关请求:这个和具体的系统相关,如果断线前的系统进行的是一些对数据敏感的操作,比如合成物品,购买物品等,在发起的时候会做无法二次点击的处理并加入到重发列表中,在网络恢复之后重发。此时如果服务器未做处理便会直接处理,如果做了处理需要服务器忽略(注,这个需要服务器配合)
2)对于战斗的后续处理
A.重新拉取战斗状态数据:这个是由于我们游戏是对战斗实时性要求较高的游戏,所以在断线过程中的战斗状态可能会发生很大的改变,这些改变必须需要重新同步,比如可能会死亡,球变大或变小,位置改变等都有可能,所以在重连之后,我们是全量拉取玩家战斗数据,同步到最新的状态。

7、对重连的一些说明
  1)在战斗过程中,其实还伴随这大厅这个连接,所以很多情况下,战斗连接的断开也会伴随着大厅连接的同时断开。对此,我们对于不同连接建立不同的重连器,从而达到两个连接相互独立,无论只是单个连接的断开还是两者同时断开,都不会相互影响,各自走各自的重连过程。

8、对之前版本游戏更加容易掉线的一些思考
  虽然其实很多时候确实是wifi不稳定导致的网络问题,但之前版本确实比其他游戏更容易掉线,具体体现在在同一个网络下,两个差不多的手机,玩我们游戏的时候掉线的频率更高,对此以下是我的一些想法。
  对于网络经常触发异常的原因,除了网络本身的不稳定外,主要还是TCP协议中,客户端缓冲区在网络不稳定的时候容易写满导致的问题。
  对于这个问题,一方面可以适当的扩大缓冲区的大小,对此把客户端网络的缓冲区扩大,从1024*100,扩大到1024*2000,也确实改善了游戏的网络状况。
  但这种方式只是并没有从本质上解决这个问题,网络其实的压力还是很大,流量过大也是我们遇到的问题之一。
  由于包头和TCP持续计时器的原因,在每个包的包头都会有一些不属于游戏协议内容的造成的流量,对于一些能够合并到一起发送的小包,合并小包和减少包量可以很大幅度的减少流量。而且也容易避免由于滑动窗口可发送部分的迅速充满导致的网络拥塞。
  另一方面,单个包的大小过大也会迅速的撑大缓冲区,而且在传输过程中造成传输峰值,造成网络延迟,拆分过大的包,比如一瞬间全量拉取排行榜等的数据通过分批拉取,减缓网络压力,也能达到优化网络的目的。

9、对于为什么会有wait状态
  其实对于一般的想法来说,其实断线重连只需要Start,Reconnect,End三种状态,确实,这三种状态可以把整个断线重连的过程完成,对于wait,主要一下几个原因。
1.Wait 状态和Reconnect状态的区别在于Wait状态手机网络并没有连接,而Reconnect状态的网络已经恢复了,这个其实是有差别的,可以对网络的状态进行不同的处理。
2.因为由于一些原因(比如在wait状态可能由于Apollo错误原因而无法收到网络恢复的消息等)我们也低频尝试了重新和服务器建立连接,但是其目的是发现是否能够建立连接,更多的时候会返回失败的消息,是一种double check 的保证策略,而Reconnect状态下的重连是我们知道了网络已经恢复,尝试去连接服务器,目的是为了真正的建立连接,这两种情况无论在目的上还是在连接的频率上都有差别,而且将两个状态区分便于我们在不同状态下做不同处理。