文章目录
做游戏通常都会用到Websocket,这个工具在前端本身的文档( Websocket-mdn)就简单得很,原理也很简单,就是http1.1的基础上增加了长链接,封装之后监听open、message、error、close,可以主动调用send、close,通常close不会主动调用。
问题表现:
机型均为15.3以上,后测试12.5没有问题,机型范围并不具体;1006 {eventType: true} 无其他报错信息。其中eventType时浏览器事件机制的只读属性,代表被信任,无信息价值。1006是保留,用来表示期望收到状态码时连接非正常关闭,无具体指向。
定位疑似原因:
数据多帧发送存在无法正确解析和解压数据的bug
解决方式:
后台建联时关闭请求头的连接确认
定位问题思路过程记录:
1、对比前端代码运行环境问题
(虽然Android运行正常,但还是仔细些好,也方便后续提供给研究问题的人证明);
结果记录:
- 检查前端对接websocket代码,并未启用close流程;
- 检查接收数据后是否解码数据影响,切换解码与不接码控制变量对比,无影响;
综上,排除前端代码问题。
2、写纯请求前端代码连接,确认是否接口部署服务问题;
结果记录:
- 后台SYNC和正常响应验证,验证没有影响。
- 走到固定流程会失败,对比流程变化怀疑接收字符长度引起的变化。后台通过直接切换返回无意义长度问题严重,200字符可以成功走完流程,500个字符不行,考虑可能时 MTU(最大传输单元)问题;但MTU大小通常是1500(最大可配置到9000)字节,且是接收到数据之后断连,而MTU问题则会丢失数据帧。
- 多次验证过程中,游戏又可以走到不同的流程,因此特定流程的后台接口影响也排除,长度的嫌疑度也降低,怀疑内容可能性增大。(后续多次验证时确认)
综上,长度是一种影响的表现,虽可作为一种解决思路,但实际表现中属于收到数据再断连,断连的引起机制还未找到;且游戏的数据结构同步已全部是关键信息,不易拆分,若使用分批次发组合数据,组合数据耗时切须维护管理,对于数据长度的拓展有一定的限制性,方案复杂没有针对性,没有实操的意义。
3、IOS连接是否有对TSL安全协议版本有要求(使用的wss协议)
结果记录:
- 查到一份资料有提到需要使用tsl1.2,后台确认服务一致;
综上,排除SSL证书问题问题。
4、验证iOS网络是否稳定&查阅信息是否iOS会出现频繁断连又迅速重连情况
结果记录:
- 断网表现报错一致,继续查看;
- iOS部分机型升级版本确实会出现Wi-Fi断连,但不会马上重连;且无websocket关键字相关;
- 多IOS手机随机测试,多网络切换,断连现象稳定频发;
- 使用浏览器的navigator.onLine及断网联网监听事件,websocket断连时网络并未断连;
综上,排除网络不好原因引起。
5、自己搞个nodedemo验证纯连接问题:
结果记录:
- 写demo测试直接断连,就很黑人问号。node库和go库的区别很大吗?
本想研究node库深入,虽然能成大功但时间紧急,也感觉这个走向有些费力不讨好,出结果的几率小。且websocket,原理简单,看了下node的主文件没有什么切入点。
6、IOS自身多运行环境对比:QQ频道应用、QQ聊天框、safari、chrome;
- 代理多环境运行代码,对比表现一致;
- 以safari为关键词搜索问题时,发现有类似问题,且关掉一个内置功能 NSURLSession Websocket 即可,验证可行。
然而QQ内部又无此功能,因此还是需要找到核心原因。
查询Safari此功能的作用,是一个新规范的压缩中间件,也就是说是存在中间件执行有问题并内部主动关闭的情况;那么就需要验证下是否有该中间件的请求头标识。
webview里抓不到wss请求包??QQ内部与外部的区别。QQ android是有实现新的???
通过抓包safari对比请求头、数据等时,发现
iOS websocket 抓包工具:Charles 、 Wireshark 、mitmproxy 、Socks5 代理(付费)。本是用whistle代理抓包来着,但是不知道为什么抓不到此次的wss请求,只得在safari中查看
- 结果预设:抓包iOS正式环境 webview 、 safari 、chrome; demo的各浏览器 ; 对比请求头
大家的请求头应该一致,ios必须具备压缩头;假设 不建立defate压缩连接 是解决办法,那么safari的两种情况表现应该有所不同;
upgrade 逐跳(Hop-by-hop)标头,connection
Sec-WebSocket-Extensions
用于指定一个或多个请求服务器使用的协议级 WebSocket 扩展。允许在一个请求中使用多个 Sec-WebSocket-Extension 标头;结果跟在一个标头文件中包含了所有列出的扩展一样。 permessage-deflate 压缩扩展;
通过对比验证,请求头标识特点符合。那么就需要关闭这个压缩功能,还原到旧的协议版本来验证是否是压缩协议实现有问题。Safari虽提供了这个功能,但是实际运行环境的QQ并没有,因此只能找到后台,找其改掉websocket建联时请求协议商定时的确认。看了go的websocket 库,同nodejs一样无配置入口,但后台大佬不负众望,改了库内部的实现。(todo-待补充)
协议建立连接之后验证,果然不再断连。
至此,虽找到并解决了关键点,但这个关键点后面还有很多牵连的知识以及疑似内部深层次的iOS- webview实现该压缩协议失败而 Android正常的根本原因需要探索。
题外
此坑是个开发时预料之外的坑,借此记录下排查问题的过程以及网上的优秀资料和贡献者们,且整理下websocket问题排查规范流程:
- 网络问题:网络不稳定、断网、网络丢包等原因都可能导致websocket断连。
- 服务器问题:服务器故障、服务器重启等原因也可能导致websocket断连。
- 应用问题:应用进入后台、应用被系统强制关闭、应用崩溃等原因都可能导致websocket断连。
- SSL证书问题:如果websocket使用的是wss协议,那么SSL证书无效或过期也可能导致websocket断连。
- WebSocket协议版本不兼容:如果客户端和服务器使用的WebSocket协议版本不兼容,也可能导致websocket断连。
参考资料:
状态码报错一览表
websocket原理
基于Tomcat的Websocket范例及permessage-deflate扩展特性的研究
The WebSocket Protocol - rfc6455协议