IM后端开发设计思想

IOS开发实训课程设计

这周确定了课程设计的方向, 做 IM(即时通信App), 我主要负责后端这个方面, 所以学习了一些可以实现的技术细节, 在这里做记录


消息通信

有一个最简单的例子, 就像发手机短信一样, 只要知道手机号码就能发出去并接收到短信, 但实际上(APP的)用户与用户之间是没办法直接了解到互相的网络信息(ip, 端口号)来进行相互通信的, 所以需要用一个服务器来做中转站的功能

假设一个场景, 用户A想要给用户B发送一条消息M, 其(简化版)过程就会是下面这样:

  • A 向服务器发送 M
  • 服务器接收到 M, 将 M 转发给 B
  • B 接收到消息

这样便实现了 A 向 B 发送 M 的过程, 这也可以解决一些问题, 如:

  • B的状态A发送M 的这个事件是 无关 的, 不必考虑各种问题(在线否, 接收到否)
  • 服务器可以控制 只有双向好友才能通信
  • 等到 B 在线, 服务器才将 M 发送出去, 确保 B 能够接收到

消息接收-离线

上面提到 等到 B 上线了, 会接收一系列发给 B 的消息, 实际上是如何实现的呢?

其实并不是服务器主动发送 未接收 消息给 B, 而是 B 上线时主动去拉取(请求)回来

具体实现

  1. 在服务端, 每个用户都会有一张消息表, 用来记录各种消息记录, 它们有着唯一标识的 序号(seq) 属性
  2. 在客户端, 存储着用户上一次最后收到的消息的 序号(rev seq)
  3. 当用户刚登录时, 会向服务端发送一个请求, 拉取 rev seq 后的全部消息, 并更新这个值
  4. 至此, 用户可以接收到自己未收到的新消息

消息接收-在线

上面说到的是 离线消息 的接收, 那么在线消息呢? 总不会要每时每刻都向服务器发送请求查询是否有新消息吧?

实际想的是 服务器接收到消息时, 先看一下用户是否在线, 如果在线, 那么直接发送给用户, 更新本地 rev seq, 如果不在线, 那么就是上面的情况;

当然服务端想直接发送信息给用户, 两者之间是需要建立连接的, 放到服务端来实现可以很大优化用户体验

具体实现

  1. 用户上线时, 与服务器建立连接(目前想法是socket连接)
  2. 建立连接后, 服务器知道哪些用户是在线的, 可以把消息直接转发给用户
  3. 用户收到消息要记得更新 rev seq
  4. 用户下线时, 通知服务器断开连接
  5. 服务器要维护在线用户状态

(具体socket连接如何实现还没想好)

消息接收表

为了更好的扩展, 用户各自的 消息接收表 并不是简单地设计成只存储 seqstring 这样的表, 因为这样只能存储一些简单的文字消息, 还要考虑到 图片/视频/语音/链接 这样的消息内容

具体实现

大致想到的表就是图中的样子吧

其中:

关键字 备注
seq 序号
from 消息发送者
type 消息类型(文字/图片/视频…)
contentID content表的id 用于查询具体内容
cid 主码
content 内容, 根据type来解读

也就是说用户可能会收到多种消息, 然后再根据 contentID 去拿回对应内容进行显示

联系人/好友

这一部分目前思考得不算太多, 大概是每个用户都有自己的好友表(单向), 添加/删除都可以实现, 这样就算重装APP也可以保留好友列表

用户信息-验证与存储

用户可以拥有多个唯一标识, 如 用户id, 手机号, 邮箱; 拥有一个密码;

用户信息包含:

  • 昵称
  • 头像
  • 个性签名

表也挺简单:

用户信息-更新

问题的来源是这样的, 当一个用户更新了自己的信息, 怎么通知其他人呢?

请教了老师之后明白了, 关键是用好之前的消息接收表

具体实现

  1. 用户更新信息, 会向TA的好友发送一条特殊的消息, typeINFO UPDATE(待定)
  2. 用户收到这样特定的消息会进行特殊处理, 在这里是更新用户信息

建立好友关系

同更新用户信息相似, 也是发送一条特殊的消息, 在客户端做特殊处理

具体实现

  1. 用户发送好友请求消息, 发送特殊消息, typeFriend Req(待定)
  2. 用户通过或不通过好友申请, 发送特殊消息, typeReq SUCCReq FAIL
  3. (若成功)服务端在好友表中添加相应用户, 客户端在好友列表添加相应用户

未来可能要考虑的内容

  • 类朋友圈内容发布
  • 多种聊天信息(视频/语音)完善
  • 表情包保存
  • 后台消息推送
  • 性能优化