问题发现

最近在写一个对战小游戏的Demo,主要玩法是两个人互放地雷击败对手。小游戏的服务端是一个基于Socket.io的转发脚本,而客户端使用的是BestHttp插件提供的Socket.IO连接库。整个游戏的预览图如下所示:
u3d对战炸弹人游戏预览

游戏运行后,客户端断线重连较为频繁,已经影响到游戏的正常运行。例如当发送地雷放置事件时,本方或对方正处于掉线状态导致该事件发送失败,客户端就无法正常响应。断线与重连的频繁程度可以参考下图:
断线重连

尝试解决

我查阅了一些资料,发现WebSocket协议是支持TCP长连接的,它定义了Ping、Pong两个事件来做心跳,以此进行长连接的维护。根据我的猜测,Socket.io理应封装了这些事件并自动维护长连接,那为什么上面连接的持续时间会这么短呢?

首先我猜测是协议问题,Socket.io会根据所处环境自动选取协议,它支持的协议如下:

  • WebSocket
  • Adobe Flash Socket
  • AJAX long polling
  • AJAX multipart streaming
  • Forever Iframe
  • JSONP Polling

于是我将链接都改成ws://开头,然而并没有什么卵用。之后,我尝试修改客户端的连接设置,例如断线重连、延迟重连等,也都没有效果。

最后,我把目光放在了服务端脚本上,既然WebSocket协议使用Ping、Pong进行心跳,那么有没有一种可能,即客户端心跳包发送间隔太长,服务器认为其超时而主动断开连接?于是我将代码进行了如下修改:
原来的服务端脚本

let server = require("http").createServer();
let io = require("socket.io")(server);

修改后的服务端脚本

let server = require("http").createServer();
let io = require("socket.io")(server,{'pingTimeout':6666666,'pingInterval':6666666});

修改完成后保存并重新运行脚本,之后开启两个游戏客户端进行对战,游戏存在的频繁断线重连问题得以解决。

猜想

由于我并不是太懂计算机网络,并且该插件也是闭源的收费插件,我只能猜测该插件在Socket.io的C#实现上有些小问题,也许是它发送心跳的间隔或处理方式与服务器API默认配置不符?不懂。

PS:在服务器脚本里设置一个超大的心跳间隔也只是缓兵之计,但对于随便写的小练习来说足够了。

我来吐槽

*

*

3位绅士参与评论

  1. 葛一速05-22 17:33 回复

    分析得很详细,提交给官网吧

  2. 后宫学长05-21 19:39 回复

    厉害,可以跟官方提解决方案了。

  3. 柠檬酸05-21 09:36 回复

    看不懂~ 😯