6

《移动IM开发指南》系列文章将会介绍一个IM APP的方方面面,包括技术选型、登陆优化等。此外,本文作者会结合他在网易云信多年 iOS IM SDK 开发的经验,深度分析实际开发中的各种常见问题。

### 通讯方式选择

IM通讯方式无非两种选择:设备直连(P2P)和通过服务器中转。

1、 P2P
P2P 多见于局域网内聊天工具,典型的应用有:飞鸽传书等。这类软件在启动后一般做两件事情:

  • 进行 UDP 广播:发送自己信息和接受同局域网内其他端信息
  • 开启 TCP 监听:等待其他端进行连接

详细的流程可以参考飞鸽传书源码。但是这种方式在有种种限制和不便:一方面它只适合在线的点对点消息传输,对离线,群组等业务支持不够。另一方面由于 NAT 的存在,使得不同局域网内机器互联难度大大上升,在某些网络类型(对称 NAT)下无法建立连接。

2、 服务器中转
几乎所有互联网IM产品都采用服务器中转这种方式进行消息传输,相对于P2P的方式,它有如下的优点:

  • 能够支持更多P2P无法支持或支持不好的业务,如离线消息,群组,聊天室服务
  • 方便业务逻辑的拓展和新旧版本的兼容

当然它也有自己的问题:服务器架构复杂,并发要求高。

网络连接方式

IM 主流网络连接方式有两种:

  • 基于 TCP 的长连接
  • 基于 HTTP 短连接 PULL 的方式

后者常见于 Web IM 系统(当然现在很多 Web IM 都是基于 WebSocket 实现),它的优点是实现简单,方便开发上手,问题是流量大,服务器负载较大,消息及时性无法很好地保证,对大规模的用户量支持不够,比较适合小型的 IM 系统,如小网站的客户系统。
基于 TCP 长连接则能够更好地支持大批量用户,问题是客户端和服务器的实现比较复杂。当然也还有一些变种,如下行使用 MQTT 进行服务器通知/消息的下发,上行使用 HTTP 短连接进行指令和消息的上传。这种方式能够保证下行消息/指令的及时性,但是在弱网络下上行慢的问题还是比较严重。早期的来往就是基于这种方式。

协议选择

IM 协议选择原则一般是:易于拓展,方便覆盖各种业务逻辑,同时又比较节约流量。后一点的需求在移动端 IM 上尤其重要。
常见的协议有:XMPP;SIP;MQTT;私有协议。

  • XMPP 协议的优点在于:协议开源,可拓展性强,在各个端(包括服务器)有各种语言的实现,开发者接入方便。

但是缺点也是不少:XML 表现力弱,有太多冗余信息,流量大,实际使用时有大量天坑。

  • SIP 协议多用于 VOIP 相关的模块,是一种文本协议,由于我并没有实际用过,所以不做评论,但从它是文本协议这一点几乎可以断定它的流量不会小。
  • MQTT 的优点是协议简单,流量少,但是它并不是一个专门为 IM 设计的协议,多使用于推送。
  • 市面上几乎所有主流 IM APP 都是使用私有协议,一个被良好设计的私有协议一般有如下优点:高效,节约流量(一般使用二进制协议),安全性高,难以破解。缺点则是在开发初期没有现有样列可以参考,对于设计者的要求比较高。

一个好的协议需要满足如下条件:高效,简洁,可读性好,节约流量,易于拓展,同时又能够匹配当前团队的技术堆栈。基于如上原则,我们可以推出: 如果团队小,团队技术在 IM 上积累不够可以考虑使用 XMPP 或者 MQTT+HTTP 短连接的实现。反之可以考虑自己设计和实现私有协议。

私有协议的设计

  • 序列化选择移动互联网相对于有线网络最大特点是:带宽低,延迟高,丢包率高和稳定性差,流量费用高。所以在私有协议的序列化上一般使用二进制协议,而不是文本协议。常见的二进制序列化库有 protobuf 和 MessagePack,当然你也可以自己实现自己的二进制协议序列化和反序列的过程,比如蘑菇街的 TeamTalk。但是前面二者无论是可拓展性还是可读性都完爆 TeamTalk(TeamTalk 连 Variant 都不支持,一个 int 传输时固定占用 4 个字节),所以大部分情况下还是不推荐自己去实现二进制协议的序列化和反序列化过程。
  • 协议格式设计基于 TCP 的应用层协议一般都分为包头和包体(如 HTTP),IM 协议也不例外。包头一般用于表示每个请求/反馈的公共部分,如包长,请求类型,返回码等。 而包头则填充不同请求/反馈对应的信息。

一个最简单的包头可以定义为
图片描述

以心跳包为例,假设当前的 serial 为 1,心跳包的 command 为 10,那么使用 MessagePack 做序列化时:length=4,serial=1,command=10,code=0,每个字段各占一个字节,包体为空,仅需要 4 个字节。
当然这是最简单的一个例子,面对真正的业务逻辑时,包体里面会需要塞入更多地信息,这个需要开发根据自己的业务逻辑总结公共部分,如为了兼容加入的协议版本号,为了负载均衡加入的模块 id 等。

上面就是 IM 系统大致的选型过程,包含了通讯方式,连接方式,协议选择,协议设计。但是实际开发过程中还有大量的问题需要处理。《移动IM开发指南》系列文章第二篇将会为大家解答实际开发中的常见问题。


随着即时通讯以及音频处理和压缩技术的不断发展,效果更好、适用范围更广、性能更高的算法和新的技术必将不断涌现,如果你有好的技术或者分享,欢迎关注网易云信官方博客和 GitHub:

关注更多技术干货内容:网易云信博客
欢迎关注网易云信 GitHub
欢迎关注网易云信官网

网易数智
619 声望140 粉丝

欢迎关注网易云信 GitHub: