转自:http://blog.codingnow.com/2014/02/connection_reuse.html

我们的手机游戏发布有一段时间了。立项之前我写的一篇 blog , 在移动设备上开发游戏需要克服的两大技术难点: 移动网络的不稳定性以及手机硬件资源的约束。由于开发时间所限,第一点我们并没有专门去做。

我一直不想动手去做一个临时方案解决 TCP 断线重连问题,因为实现一个 TCP over TCP 是没有太大意义的。移动网络发展迅速的今天,整个行业都在努力提高移动网络的稳定性,所以费力做这个事情很可能在两年之后就变得完全没有必要。

比如,iOS 7.0 发布 后,让 MultiPath TCP 技术为更多人所知。从许多中文资料对其的解读,主要集中在 MPTCP 提供了更大的带宽上;甚至一些网络喷子借机来喷国内的 3G 收费高的问题,认为同时利用 3G 网络和 wifi 下载没有意义。但我认为其对于移动网络的真正意义在于提供一个更加稳定的连接。

顾名思义,MPTCP 允许在同一 TCP 连接的通讯两端建立多条通讯路径,如这篇文章 所言:Just like IP can hide routing changes, MPTCP can hide the details of which paths it is using at any given time.

这两天,我们在自己的服务器上安装了支持 MPTCP 的新内核做了测试。发现:如有可能,设备会为新的 IP 地址建立新的通讯路径。如果连接两端各有两个 IP ,那么在初始的 TCP 连接建立后,通过协商,最终会建立 4 条 TCP 连接出来,交叉连接了所有的 IP 。任何一条通路有效都不影响通讯。btw, 如果你的机房有网通,电信两个 IP 的话,如果客户端设备支持 MPTCP ,那么会自动同时使用两个通路同时维持一个逻辑上的连接。这对国内的网络环境非常有利,不需要使用 bgp 机房,也不需要在多线机房配置复杂的 DNS 了。

当你的手机从 3G 网络切换到新的 wifi 热点时,设备会自动利用新的 wifi 网络做数据传输;离开 wifi 热点后,又能无缝切换回 3G ;再次进入新的 wifi 热点范围,还可以重新利用新的 wifi 网络。这样,移动设备可以穿梭于多个网络之间而永不断开连接。

可惜的是,Apple 目前并没有完全开放 MPTCP 给应用层使用。经我的测试,只有 Siri 的连接才会发送 MPTCP 握手协商。这篇 blog 也证实了这一点 。

ps. 经过这两天的测试,还发现 MPTCP 似乎只能利用第一次连接的通路做控制信息交换。当第一次连接的 IP 实效后,不能把后来的通路提升为主控连接。所以 MPTCP 看起来不能在只有一个网络设备上正常工作。(我原先预期它可以在同一个设备上切换 IP 还可以正常建立新的子流,看来是搞错了)


借着阅读 MPTCP 的协议文档,我也想了许多。我觉得在现阶段在应用层上实现一个更稳定的 TCP 连接也是可行的。但协议设计要考虑的很多,下面记录一下我的设计方案:

我希望针对游戏服务器的特性,实现一个不对称的连接协议。即,只能由客户端发起连接,而发起连接的一方无法主动断开连接。服务器只接受连接,有权利断开连接。

这个协议基于已有的 TCP 协议,通讯是基于带长度信息的包构成。客户端到服务器的前两个包为握手包,服务器只用回应第一个握手包,客户端发送的第二个握手包用于校验,当服务器不认可握手过程,可直接断开连接。

连接建立过程如下:

.1. 客户端向服务器发起一个 TCP 连接,并发送第一个握手信号:包含一个 0 和按 Diffie-Hellman 密钥交换算法产生一串随机量 A 。

.2. 服务器收到第一个握手信号后,检查第一个字段,若不为 0 则进入连接修复阶段 2.2,否则继续创建连接过程 2.1。

.2.1 此时服务器生成另一个随机串 B ,并通过 DH 密钥交换算法得到了一个 secret 。此时回应 DH 算法需要的 B ,以及一个新的随机串 E (用于校验)。

.2.2 当第一个字段不为 0 则认为是需要修复一个已有连接,这个数字表示在旧连接上客户端已收到过服务器发过来的数据包数量。此时,第二个字段应理解为旧连接上已收到数据包的指纹。服务器根据包数量和指纹可以核对所有保持的有效连接,如果不能找到匹配的连接(指纹相同),就断开客户端。否则回应客户端在旧连接上一共收到客户端发送的数据包数量,以及一个新的随机串 E ,用于确认客户端是否知道旧连接的 secret 。(这个校验是有必要的,否则会有人监听到链接重建过程,而重复发送这个握手包来踢掉合法用户刚修复的连接)

.3. 客户端收到随机串 E 后,和 secret 连接在一起做一次 hash (可以使用 md5 算法) H,回应服务器。这可以让服务器校验客户端是否真的拥有 secret 。

.4. 服务器收到二次握手信号 H 后,用同样的 hash 算法做一次 secret 校验,确认是合法的客户端后继续通讯;若是非法连接则立即断开。

.5.1 如果是新连接,那么服务器利用得到的 secret 初始化 RC4 加密算法需要的 s-box ,之后的通讯利用 RC4 算法加密。

.5.2 如果是旧连接修复,那么服务器将客户端未收到的数据包重发一次。并从旧通道上复制 RC4 所用的 s-box 以及 secret 用于后续通讯。

.6. 此后的每次数据通讯,在数据打包后,都利用 RC4 算法做一次加密,并利用数据更新数据指纹(可以用加密后的数据流的 CRC 值)。每个数据包都记录当前的指纹,并 cache 最近发送的 128 个数据包用于事后的连接修复。

.7. 设定一个超时时间,定期清理没有数据来往的 TCP 连接。

这个协议的好处是,客户端在握手完成后,任何时间都可以向服务器发起一个新的 TCP 连接取代旧的连接(无须利用旧连接是否还有效),而对应用层来说,连接重来没有中断过。

应用层可以做一些配合工作:比如设计一分钟一次的心跳,如果长时间没有收到心跳包,就主动发起新的 TCP 连接去取代旧的。这对无线网络能增加网络的稳定性。比如你切换 wifi 网络时,由于 IP 地址的变化, TCP 连接不可能保持,但这套协议可以帮助你自动修复它。在没有 MPTCP 支持时,它还可以尽量去使用更高质量的网络(只要重新连接时去尝试新的网络设备即可)。


我计划在 skynet 中实现一个和网络 API 无关的 C 模块作为中间层来完成以上工作:

接口大约是这样:

struct socket_pool;// when sz == 0 and buffer == NULL, fd is closed
// when sz > 0 and buffer != NULL, buffer is the data
struct socket_package {int fd;int sz;const char * buffer;
};struct socket_pool * socketpool_new();
void socketpool_release(struct socket_pool *sp);
void socketpool_timeout(struct socket_pool *sp);void socketpool_pushinput(struct socket_pool *sp, int fd, const void * buffer, int sz);
void socketpool_pushoutput(struct socket_pool *sp, int id, const void * buffer, int sz);int socketpool_popoutput(struct socket_pool *sp, struct socket_package *p);
int socketpool_popinput(struct socket_pool *sp, struct socket_package *p);void socketpool_closefd(struct socket_pool *sp, int fd);
void socketpool_close(struct socket_pool *sp, int id);

fd 是底层的 socket handle ,id 是应用层的连接 id 。

当网络层有任一 fd 收到数据时,通过 pushinput 接口把数据推送到 socketpool 中。调用 popinput 会报告哪个 id 上有新的数据包(或是没有新的数据包)。

向一个 id 写数据只需要调用 pushoutput ,然后反复调用 popoutput 可以得到真正需要将哪些数据写入具体的 fd ,把它们交给网络层 API 发送即可。

如果有 fd 断开,或向主动关闭 id ,可以调用 closefd / close ;而 popoutput 则有可能收到一个 fd 关闭的信号,然后调用网络层 API 去对应的 fd 即可。

这个模块会处理数据打包加密,修复连接重新补发包等问题,并将这些隐藏在实现中。


2 月 14 日补充:

我实现了一个开源版本, API 有所不同。目前尚未仔细测试,有兴趣的同学可以一起来完善它。

在移动网络上创建更稳定的连接相关推荐

  1. desktop不可用。如果该位置位于这台电脑上,请确保设备或驱动器已连接,或者光盘已插入。如果该位置位于网络上请确保已连接到网络或Internet,然后重试。如果仍然找不到该位置,则他可能已移动或删除

    desktop不可用.如果该位置位于这台电脑上,请确保设备或驱动器已连接,或者光盘已插入.如果该位置位于网络上请确保已连接到网络或Internet,然后重试.如果仍然找不到该位置,则他可能已移动或删除 ...

  2. 在桌面上创建一个宽带连接服务器,win7宽带连接怎么创建桌面

    win7系统是一款大家用了都说好的系统.最近一直有小伙伴们在问win7宽带连接怎么创建桌面的问题?今天小编就为大家带来了win7宽带连接创建设置一起来看看吧. win7宽带连接创建设置: 1.点开始, ...

  3. 在桌面上创建一个宽带连接服务器,win7系统怎么在桌面上创建宽带连接的快捷图标?...

    腾讯视频/爱奇艺/优酷/外卖 充值4折起 说到"宽带连接",每个上过网的人都记得,在刚去电信或联通开户后,电脑每一次上网就是要通过点击"宽带连接"这个图标后才能 ...

  4. 在桌面上创建一个宽带连接服务器,win7怎么在桌面上创建宽带连接图标 桌面上创建宽带连接教程...

    如果我们想要上网的话一定要进行宽带连接,除非你通过路由器或者其他共享,但是在路由器上的那台电脑也要配置宽带连接,如果系统重装了或由于个人操作引起一些文件丢失而使电脑上的桌面没有"宽带连接&q ...

  5. 在桌面上创建一个宽带连接服务器,win7在桌面上创建宽带连接快捷方式的方法...

    现如今大多数家庭都使用宽带拨号连接作为上网方式,也是最传统的连接上网方式,但是一些用户重装win7旗舰版系统后,发现桌面并没有宽带连接快捷方式,每次都要通过右下角的小图标连接宽带,这样操作起来比较麻烦 ...

  6. 标注图像 创建cnn网络_如何在网络上创建图

    标注图像 创建cnn网络 Sometimes you just need to make a decent-looking graph, but don't want to get bogged do ...

  7. 去中心网络上的内容寻址

    Content Addressing on the Decentralized Web Identifying and retrieving data on the web How we identi ...

  8. JScript 和 VBscript访问网络上的打印设备

    Network 对象使您能够访问有关网络的信息.下面的脚本将演示如何映射网络驱动器.首先,脚本将创建一个 Network 对象.接着,MapNetworkDrive 方法(Network 对象的一个方 ...

  9. 鲸鱼网络连接_登陆鲸鱼:在网络上读书,第1部分

    鲸鱼网络连接 I don't know when it was I started using the text of Moby Dick in my workshops and talks. Lik ...

最新文章

  1. MongoDB Windows环境安装及配置
  2. OpenCV C++ 07 - Histogram Equalization of a Color image with OpenCV
  3. 【五】每个球队胜率统计
  4. 企业网站前端制作实战教程 JQuery CSS JS HTML 登录界面
  5. java验证xml格式是否正确的是_spring源码附录(1)java实现对XML格式的验证
  6. Java 接受reactjs数据_ReactJS:从API获取数据
  7. 大型网站的架构设计问题—-大型高并发高负载网站的系
  8. TCP实现多线程下文件的上传
  9. yandex 浏览器 linux,业界动态
  10. vue加跨域代理静态文件404_解决vue-router history模式和跨域代理 部署到IIS时404的一些问题...
  11. aix 查看防火墙状态_aix防火墙怎么样设置
  12. oncreate 测量尺寸
  13. Snagit 2020 for mac(最好用的屏幕截图软件)
  14. 畅购商城项目 订单+用户认证+微信扫码支付+订单处理
  15. VS2013MFC对话框工程学习笔记二 - 了结布局和一些基本的窗口组件
  16. 经典笔试面试题(二)
  17. NYOJ - 独木舟上的旅行(贪心)
  18. 云服务器测速脚本_服务器性能自动化测试脚本
  19. 慕尼黑大学计算机语言学,慕尼黑大学,斯图加特大学和萨尔大学的计算语言学硕士如何选择?...
  20. 前端 100 问:你会多少?

热门文章

  1. 〔王鹰教程五〕和弦的分类记忆法
  2. 天津科技大学计算机西电,学通信工程专业,大学四年该如何规划?谢谢
  3. PDPS汉化包安装与语言界面切换操作
  4. 如何做人做事?方与圆的为人处世之道
  5. linux安装perf工具
  6. 华为电脑如何投屏到电视linux,华为 P30 如何投屏到电脑
  7. bootstrap4学习路线
  8. SAS9.4更新sid,有效期至2022年11月30日
  9. Mysql客户端navicat的使用并连接远程数据库【重点】
  10. 运用百度框架paddle进行手势识别【动手实践,附源码】