iOS开发 之 消息推送技术研究

目录

  • 引言

  • 消息推送

  • Socket

  • WebSocket

  • 其他方案

  • 心跳

  • 附录

引言

现在的移动端开发, 消息推送是一个标配的必备功能, 工作中要开发的产品当然也不能"幸免"

不过或许你会说, 接入第三方不就得了 -- 为开发加速(LeanCloud的广告语, 表示感谢)

  • 极光

  • 腾讯信鸽

  • LeanCloud

...(在此略过100家)

但是有些情况下, 偏偏一不小心就选择了自己去实现这条"不归路", 所以就有了深入研究这件事

即使开发中选用了第三方方案, 但从知识结构和职业发展的角度来看, 研究这件事总是没有错的

消息推送

顾名思义, 消息推送就是上行发送消息到下行, 服务器发送消息给终端

如果是你, 会如何实现服务器发送消息给终端呢?

  • 把终端变成服务器, 服务器变成终端, 这样来发送(其实是请求)消息 (脑洞大开的感觉有没有...)

  • 终端不断滴去服务器请求, 有消息就取到, 结果和服务器推送消息看起来是一样一样的 (好像还蛮靠谱的...)

  • 在终端和服务器之间保持一条一直连接不断开的双向通道 (看起来很完美啊, 就他了...)

第一种方法太"高端"了, 远超本人的能力范围, 所以暂不讨论

第二种方案有两种常见的实现方法

  • ajax轮询 - 终端隔个几秒就发送一次请求, 询问服务器是否有新信息

  • long poll - 又叫阻塞式轮询, 即终端发起连接后, 如果没消息, 服务器就一直不返回Response给终端

缺点也是很明显的

  • ajax轮询 - 消耗服务器的运算处理资源 (速度)

  • long poll - 消耗服务器的并发处理资源 (场地)

第三种方案看起来最完美的, 也是现在消息推送的标准实现, 它有以下几种实现方法

  • Socket

  • WebSocket

  • 其他方案(这是什么鬼? 这里泛指除Socket和WebSocket的所有方案)

你确定上面"两个Socket"不是一个东西么?

这里确定, 一定以及肯定的告诉你, 这两者的关系比Java和Javascript的关系还要远(详见下文)

Socket

这里的Socket特指网络编程中的Socket

Socket中文名: 套接字, 它有两个特征

  • 它不是协议而是一套APIs

  • 它实现的是双向通信

Socket APIs是对TCP/IP协议的封装, 它可以分为面对连接的基于TCP的Socket和应用于无连接的基于UDP的Socket

Socket建立连接的流程大概是这样的

  • 服务端利用Socket监听端口

  • 客户端发起连接

  • 服务端返回信息, 建立连接, 开始通信

  • 客户端, 服务端断开连接

Socket与HTTP的区别

HTTP是基于TCP的应用层协议, 而Socket是对TCP/IP进行封装的一套APIs, 它可以基于TCP也可以基于UDP

HTTP是短连接(在先不要讨论Keep Alive什么的情况下), 每次请求返回结束后, 连接就会断开

Socket是双向长连接的, 连接通道会一直保持, 直到连接断开

Socket的实现

Socket最常用的iOS第三方库出自robbiehanson/CocoaAsyncSocket

WebSocket

什么是WebSocket? 我们先看下维基百科的权威解释

WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议

在WebSocket API中, 浏览器和服务器只需要做一个握手的动作, 然后, 浏览器和服务器之间就形成了一条快速通道, 两者之间就直接可以数据互相传送

PS: 看完Wiki我的第一感受是, 词条编辑这家伙是ABC吧, 抑或语文是体育老师教的

按照"国际惯例", 我们来从中提取出一些关键词(这个方法充分回避了我语文不好的缺点)

  • HTML5

  • 基于TCP

  • 全双工通信

  • 协议

作为新技术新协议的WebSocket有如下一些优势

  • 实时交互(所以在IM中广泛使用)

  • 服务器能够主动推送内容

  • 只需要建立一次连接、快速(延迟小, 每条消息可以小到两个字节)

  • 开发者友好(接口简单)

WebSocket与Socket的区别

两者虽然都是应用于双工通信的长连接, 但是实现和概念是完全不同的

WebSocket是协议, 而Socket是一套APIs

WebSocket与HTTP的关系

两者都是应用层协议, 这个算不算关系?

其实两者还真有点关系, WebSocket用了HTTP的协议来完成一部分握手

WebSocket的实现

最火的当然是socket.io莫属了, github star 2w+

iOS最好用(本人自己测试的)的出自facebook/SocketRocket

详细Demo可以参考SocketRocketDemo, 服务器端测试环境基于websocket.org

其他方案

上述Socket和WebSocket其实说的都是长连接, 那有没有其他方案了呢?

答案是肯定的, 而且就在我们身边: HTTP

HTTP不是短连接的么?

是的, 在HTTP/1.0默认情况下确实是这样的

但是HTTP是一个发展中的功能庞大且复杂的协议

它实现长连接的魔法就是Header中的Connection: Keep-Alive

在HTTP/1.1中, Keep-Alive已经是默认打开的了, 并且HTTP/1.1是支持双工通信的

不过坏消息是, HTTP/1.1基本已经处于死亡状态(猜测这里也有WebSocket的功劳)

它的继承者HTTP/2作为新的标准继续前进(对HTTP/2并不是很熟悉, 所以就不误导人民群众了, 欢迎"砖家"指导和补充)

除了HTTP协议之外还有没有其他方案了呢?

答案当然还是肯定的: 自研

大厂如企鹅, 底层都是自家实现的

优点如汽车手动挡vs自动挡, 缺点就是烧钱(具体实现暂不清楚, 所以在此就不继续讨论了)

心跳

长连接都有这样的问题: 如何保证长连接通道的可靠性

讨论之前先要明确的是, TCP长连接本质上是不需要心跳来维持的

因为TCP是面对连接的协议, 可以通过Keep-Alive来保证连接

那么为什么还要心跳呢?

  • Socket是基于TCP或UDP的, 所以基于UDP的Socket是需要心跳的

  • 心跳可以说明应用能否正常运行, 而TCP由操作系统负责, 所以在应用进程阻塞、死锁时TCP仍然可以发送Keep-Alive消息

  • 防止NAT超时, 大部分移动无线网络运营商都在链路一段时间没有数据通讯时, 会淘汰NAT表中的对应项, 从而造成链路中断

以下是部分地区网络NAT超时统计(引自微信Android客户端后台保活经验分享)

地区/网络 NAT超时时间
中国移动3G/2G 5分钟
中国联通2G 5分钟
中国电信3G 大于28分钟
美国3G 大于28分钟
台湾3G 大于28分钟

为了兼容国内网络要求, 我们至少需要5分钟心跳一次

老版本的微信是4.5分钟发送一次心跳, 运行良好(该结论引自微信Android客户端后台保活经验分享)

心跳的进一步优化可以移步参考微信Android客户端后台保活经验分享&[转]微信的智能心跳方案

附录

socket.io

websocket.org

趣解WebSocket

闲说HeartBeat心跳包和TCP协议的KeepAlive机制

微信Android客户端后台保活经验分享

[转]微信的智能心跳方案

Android推送技术研究

更多文章, 请支持我的个人博客

你可能感兴趣的:(iOS开发 之 消息推送技术研究)