本文在编写时参考引用了博客作者“Jack Jiang ????” “IM开发快速入门(一):什么是IM系统?”的相关资料,表示感谢。
IM的应用场景:IM广泛应用于聊天、社交等典型应用中,同时在聊天,直播,在线客服,物联网等所有需要实时互动、高实时性的场景中都有所应用。
例如熟为人知的场景:
- 1)微信、qq、钉钉等主流IM应用:这是IM技术的典型应用场景;
- 2)微博、知乎等社区应用:它们利用IM技术实现了用户私信等点对点聊天;
- 3)抖音、快手等直播/短视频应用:它们利用IM技术实现了与主播的实时互动;
- 4)米家等智能家居物联网应用:利用IM技术实现实时控制、远程监控等;
- 5)滴滴、Uber等共享家通类应用:利用IM技术实现位置共享;
- 6)在线教育类应用:利用IM技术实现在线白板
IM典型架构如下:
- 1)客户端:作为与服务端进行消息收发通信的终端;
- 2)接入层:也叫网关层,为客户端收发消息提供入口;
- 3)逻辑层:负责IM系统各功能的核心逻辑实现;
- 4)存储层:负责IM系统相关数据的持久化存储,包括消息内容、账号信息、社交关系链等;
- 5)第三方服务:保证APP在未打开或后台运行时也能收到消息通知(这主要是第三方消息推送服务)。
对于接入层,它的职责最为关键,具体是:
- 1)保持海量用户连接;
- 2)解析协议,对传输内容进行编解码;
- 3)维护客户端的连接(也叫“Session”);
- 4)推送消息。
IM技术的特性如下:
- 可靠性
指保证消息的不丢失及不重复,是IM的重要特性。
- 实时性
指保证消息的实时送达,作为IM技术的关键意义。
- 安全性
指保证数据传输安全,数据存储安全,消息内容安全,是IM系统不可少得特性,尤其是在私聊的场景下,聊天记录的隐私性尤为重要。
- 一致性
对于单聊消息来说,同一设备的时间顺序,不同设备的蛮有同步,是相当重要的一环,IM系统中的消息交互,应当保证其前后顺序一直, 不允许前言不搭后语以及胡言乱语式消息的出现。
IM的功能组成
- 1)联系人列表;
使用IM系统的第一步,就是要解决“跟谁聊”的问题。从功能表象上来说,联系人列表也就是社交关系列表,无非就是个信息列表界面,有什么特殊的地方?
联系人列表看似简单,实际上它是一系列IM系统的社交关系确立动作的结果体现。
要想建立联系人列表,你可能需要实现以下逻辑:
- 1)怎么能找到想要聊天的人?(需要实现随机查找?精确查找?)
- 2)怎么决定要不要跟这个人聊?(需要实现对方的个人信息查看)
- 3)开始发出好友请求;
- 4)被请求的一方,还可以决定是“同意”还是“拒绝”(“同意”该怎么处理?“拒绝”又该怎么处理?)。
总的来说,联系人列表的建立,是一个IM系统聊天关系确立的表现,不可或缺。
- 2)聊天界面;
是IM系统客户端的核心功能所在,所有主要的IM功能都是通过它展现。
它应该具备的能力有:
- 1)各种聊天功能按钮:语音留言、图片、文字、表情、文件、实时电话、实时视频等;
- 2)各种聊天消息显示:各种消息都有不同的UI显示元素和处理逻辑;
- 3)流畅的使用体验:大量不同类型的消息显示时,不能卡顿;
- 4)即时显示聊天消息:网络线程收到的消息,要马上在UI上显示出来;
- 5)历史消息的加载:上次聊过的内容也得显示出来吧。
- 3)消息发送通道;
上图所示,消息发送通道这个比较好懂,最浅显易懂的理解就是用tcp或udp,建立socket长连接,需要发消息的时候,wirte一下就过去了,好简单!
但,事情往往不是想象的这么简单:
- 1)如何保证这条socket长连接时一直处于可用的状态?
- 2)当socket长连接不可用时,用户此时发送的消息该怎么处理?
- 3)怎么保证发送的消息不丢?
- 4)怎么保证发送的消息不复重?
- 5)怎么保证发送的消息乱序?
- 6)当对方不在线时,发送的消息去哪了?
- 7)发送的消息,能保证实时送到?
- 4)消息接收通道;
正如上节中的消息收发通道示意图所示,消息接收通道也很好理解,对方通过消息发送通道write的消息,我得收到并显示啊。
要实现一个可靠的消息接收通道,也并非易事:
1)如何保证socket长连接通道能随时处于良好的边接状态(随时接收对方write的消息);
2)当socket长连接断开时,对方发送消息该怎么实现?
3)当socket恢复连接时,怎么恢复之前的聊天现场?
4)当我收到对方的消息时,对方怎么知道我已经收到了?
5)当重复收到对方的消息时,该怎么处理?
6)当收到的消息时序有错乱,该怎么处理?
- 5)消息存储;
消息存储这个功能好理解,聊天的消息如果存储,下次再聊的时候就不知道之前聊过什么,做不到这一点,这个IM系统的聊天体验好不起来。
那么,哪些情况下需要进行消息存储呢:
- 1)对方不在线时:聊天消息应该存储(这叫离线消息存储);
- 2)对方在线时:聊天消息也要存到本地存储(这叫消息缓存);
- 3)对方在线或不在线时:聊天消息都要存到服务端(用于实现多设备的消息漫游和同步)。
具体要存储的内容和时机也就上面这几样。
但技术落到实处,要做的事情同样少不了:
- 1)离线消息该怎么多久?
- 2)图片、短视频、大文件这类的离线消息,多媒体文件该怎么存(有可能量会很大)?
- 3)当本地的消息积累太多时,怎么能保证本地存储的性能?
- 4)当应用更新、升级或异常时,怎么能保证本地存储的完整性(不被破坏)?
- 5)怎么能保证多设备消息能不丢、不重、不乱?
- 6)消息未读数。
- 1)未读数是客户端实现还是服务端实现?
- 2)会话未读和总未读怎么保持一致?
- 3)多终端情况下,怎么保证未读数的一致性(我在这台设备上读没读,那台设备怎么知道的?)?