最近开发了一个iOS应用,依赖于websocket长连接,然而提审的时候被拒了。 从审核员提供的截图和服务端的日志来看,审核员手上的设备会不定时断开websocket连接,时长大概在30秒-1分多钟之间。 开始以为是美国连接我们服务器的线路有问题,遂通过科学手段让iOS的出口IP变成美国IP,竟然真就复现了这个问题。
查看客户端的日志:
Error Domain=NSPOSIXErrorDomain Code=54 "Connection reset by peer" UserInfo={_kCFStreamErrorCodeKey=54, _kCFStreamErrorDomainKey=1}
故而认为是服务端先动的手,找服务端查看websocket连接日志,不想服务端也认为是客户端先动的手,收到了1006
的异常信息。
查了下Google得到以下信息:
状态码 | 名称 | 描述 |
---|---|---|
1006 | CLOSE_ABNORMAL | 用于期望收到状态码时连接非正常关闭 |
websocket正常关闭的时候需要发送handshake close
,如果没有发送就会触发1006
错误。
所以我们猜测是网络问题,发生了瞬间断网又恢复的行为,但是想想苹果的网络不至于比我们公司还差吧。
后来浏览到这篇文章,其中一句话写到
在客户端和WebSocket服务器之间的全双工连接中,有时候连接上可能没有数据流。在这个时候,网络中介可能中止连接。
灵光一闪想到会不会是我们设定的心跳间隔太长了,苹果的路由器认为这是一个空连接而回收掉了,遂把心跳间隔改成5秒一次,测试发现问题解决了,于是经过测试让服务端把心跳间隔改成10秒一次。原先心跳间隔是120秒。