1、背景
移动网络信号波动频繁,给移动游戏开发者带来诸多困扰,处理不好会造成较差的用户体验以及重复扣道具等严重问题。因此弱网络问题在TDR技术评审中作为客户端重点挑战项,并且弱网络专项测试达标后方能上线。本文就过往项目中遇到的问题给出一种比较通用解决方案。
2、网络连接方式
通常游戏客户端都是通过创建socket与服务器取得连接,但也会根据使用场景划分成两种连接方式:TCP连接和HTTP连接。
1) TCP连接即我们常说的长连接。这种连接方式下socket连接一旦建立,通信双方即可相互发送数据,直到一方终止连接。目前公司的移动端联网游戏多采用这种数据通讯方式。
2) HTTP连接即我们常说的短连接。这种连接采用的是“请求-响应”的通讯方式,每次交互由客户端发起请求,服务器收到请求后才能回复数据,数据传输完成后,socket连接便断开。在下载CDN资源或云配置时通常会采用这种连接方式。
3、网络检测
3.1 检测设备的网络环境
iOS和Android都提供了检测本地网络环境的方法,具备我们需要的功能:
1) 网络环境标识,区分当前网络环境:WIFI/WWLAN/NOTREACHABLE等。
2) 网络切换感知,网络环境切换后会收到系统消息。
在苹果开发者网站(developer.apple.com)上有一个reachability的例子,对底层网络组件做了封装,可实现此上的功能。Android上提供了Connectivity Manager服务,可加以封装实现同样的功能。附录中提供了相关的开源代码,并分别封装了reachability在iOS和Android平台上的实现。
3.2 检测心跳超时和回包超时
心跳即每一定时间间隔(假定15秒)客户端和服务器进行一次请求/应答,来判断对方是否存活。若客户端发送请求成功后,长久(假定60秒)未收到服务器的回应,则认为连接已经中断或者服务器宕机。若服务器长久(假定300秒)未收到客户端请求,则可以认为客户端已经离线。另外常规的业务数据包也可以认为是心跳包的扩展,所以每次业务数据包通信成功,客户端和服务器都要重新计时。一般心跳包是一个空的数据包,以节约流量,但通常也会包含少量字段,比如客户端和服务器的时间同步信息等。
一些关键协议,比如进入房间的请求,需要等待服务回应后才能扣除体力进入房间。但网络不稳定时,可能客户端的请求发送成功,服务器的回应却迟迟没有收到,这种情况下,客户端需要做一个超时控制,比如15秒后客户端还没有收到回包,则给出提示,不能让客户端无限的等待。这种因果关联的一对协议我们称作请求-应答协议,建议所有关键协议都采用这种机制。有一点要注意,这种异步操作有一个等待的时间,一般这段时间都会屏蔽输入(转菊花/show activity indicator),避免用户进行其他操作导致重复请求。这也要求我们在代码逻辑层面上避免多个关键协议的嵌套和并发。
3.3 检测发包失败
一般来讲reachability足够灵敏可靠,设备网络发生变化时能及时感知,只要监听到状态切换为NOTREACHABLE便可认为断线了(需要排除瞬断的情况),但reachability也有限制,无法感知到传输层连接断开。举个例子:手机和无线路由器连接正常,但是无线路由器和modem连接中断,这时reachability是检测不到网络断开的。此时需