即时通讯软件设计(一)

时间:2021-12-19 17:00:05

之前写了移动市场的浅谈,当时是想紧接着写这个系列的。包括即时通讯、播放器等。后来因为要回家定亲加上要看房子,拖延了下来。今天接着写,算是上班打酱油吧。也趁此机会骂下楼市,真心黑。破县城都四千多五千。废话不说了,说正题了。

做一款软件,首先需要明确的不是你是单机的还是分布式的,cs的还是bs的。这些都是后话。第一个遇到的问题是这款软件要实现什么功能,也即是市场以及设计者开发者对于这款软件的需求预期是什么。

因为即时通讯软件是比较成熟的了。所以功能就很好列出来。对于功能,最实惠一目了然的描述方法就是用例图了。不过悲剧的是公司把端口给禁用了,上传不了图片。万恶的公司。所以这里我就简单罗列下了。

功能列表:

  • 聊天:这个会包括三种方式(语音聊天、视频聊天、文字聊天)。其又扩展为两个场合(单人、多人)。其中文字聊天又包括文本、表情、图片。其中表情可扩展为基本表情、自定义表情。
  • 传输:扩展为两种,文件传输、文件夹传输。其中功能点要包括:在线传输、离线传输。而且需要实现断点续传。
  • 频道:其实这个和聊天应该归属一个功能点下面的两种。也可以说类似多人聊天,唯一不同的就是弱管理。用户自己可申请开户,然后再分到的频道中发布相关信息,其他用户可通过搜索频道进入该电台,然后在其中进行接受信息,并支持交互。
  • 外围方面,在硬件方面,包括移动端、PC端接入程序。即用户可以使用手机、平板、PC等登陆。
  功能列表已经列出来了,下面就是探讨这个软件的结构怎么部署了。所以他的deployment如下:

  • 客户端:即用户接入程序。通过接入程序,用户可以实现上面的所有功能。这个包括pc版本、平板版本、手机版本等。具体还要适配一大堆类型出来。工作量不可小觑,不过总体而言,他的开发策略就是原型式的,一处编写到处修改。所谓适配就是改改改。
  • 服务器:负责处理一些必要的后台信息,如用户登陆时的相关鉴权以及信息登记。 因为服务器不需要适配不同的机型。服务器用什么是我们说了算,终端用户也不关心。所以在初期可以直接指定windows还是linux下的某一款。此处就暂定windows了。这边适用的开发策略就是迭代式的了,因为功能繁多,慢慢迭代吧。个人不觉得迭代属于敏捷开发,可能缘于个人对于敏捷的排斥,始终觉得这就是骗子,混饭吃也就罢了,还坑爹。尤其看到那些什么敏捷开发交流大会,个人感觉与传销无异。
即时通讯的部署的大致框架也说了,现在就是来看看技术难点了。一些不会扩散的功能点上的难点,其实不算难点。慢慢做就行了。所以软件设计初期要考虑的是那些容易扩展全局的难点,就像癌症在血液里,不搞定,小心全身崩溃。一些指甲发黑之类的,先拿刀剁了放旁边,等哪天搞定了再接上来就行了。不过一些虽然会扩散全身的,但是束手无策的,个人感觉就当不存在就行了,反正没招。

即时通讯,对于互联网第一个遇到的问题是负载的问题。服务器的能力毕竟有限。这个时候不得不考虑第一个服务器进行专职化,就是多些服务器,各尽其职。重要的就是彼此之间职责要清晰。于是就出现了几个服务器,第一个是专门用来接收用户登录的,负责鉴权以及更新数据库。第二个是专门负责通信的,即用户与用户想互相说话,因为网络问题,他们自己说不了,于是找了个中转站。但是负载的问题依然存在,客户多了,通信量大了,通信服务器扛不住。于是就想到了两个办法,第一就是治标不治本的办法,搞集群,一大堆中转服务器,但是瓶颈依然存在。第二个就是分流,能不通过通信服务器的就别走通信服务器了,于是就想到了P2P。经济实惠的办法还是P2P吧,虽然他的实现对于网络有一些要求。

于是乎整个软件的结构就清晰了。他主要包括:客户端、服务器两块。其中服务器分:登录服务器、通信服务器。具体会话的流程如下描述。

  • 登录:用户首先登录服务器,表明自己在线。用户连接登录服务器的指定端口,发起登录请求。请求中携带必要的鉴权信息。登录服务器找鉴权服务器进行鉴权,并根据鉴权结果跳转处理策略。如果鉴权成功,则生成唯一的合法性SESSIONID(其中SESSIONID的一部分由用户唯一ID组成),并将连接信息以及改ID打包交付数据库服务器,其中状态位标注为登录,数据库服务器负责入库操作,存入的表为状态表,并返回是否入库成功。登录服务器根据数据库服务器的返回结果继续跳转处理策略。如果成功,则回复登录成功的消息给用户,并在消息体中携带连接服务器的相关信息以及SESSIONID。如果失败则回复客户端服务器繁忙,稍后再试。数据库服务器定时扫描该状态表,如果超过30s,而且状态为非在线状态的,则删除该记录。
  • 连接:用户接收到登录服务器的返回结果,如果失败,直接提示用户即可。流程结束。如果成功,则从消息体中获取连接服务器的信息,释放与登录服务器的连接,并使用之前的端口与连接服务器进行尝试连接,连接失败,直接提示用户网络超时。如果连接成功,则发送连接请求信息,其中消息体携带SESSIONID。连接服务器接收远程连接之后,首先将其套接字标注为未初始化,当接收到客户的连接请求时,从消息体中回去SESSIONID,然后将客户端的连接信息以及SESSIONID打包发送至数据库服务器进行进一步合法性检查,如果数据库服务器发现其一致,则回复合法,否则回复非法。连接服务器根据数据库服务器的回复进行跳转处理策略。如果接受到的是非法,则直接拒绝,强制中断客户端的连接。客户端发现连接被强制中断之后提示用户服务异常。如果合法,则将SOCKET状态更改为连接。并发送命令至数据库服务器查询该SESSIONID对应的用户的相关信息,如好友列表、头像、个性签名等等,消息中并且携带在线好友,数据库服务器接收到该消息,首先将之前纪录的状态更新为在线,然后去查询相关表,将查询到的信息打包返回至连接服务器。连接服务器接到信息之后转发给用户。数据库服务器定时扫描状态表,并通过连接服务器以保证客户端信息同步。
  • 用户需要发起会话时,首先对连接服务器发起会话请求信息。连接服务器发送响应消息至A,消息体中携带通信服务器的相关连接信息。A接收消息后,根据消息体中的信息对通信服务器建立TCP连接。
  • 消息中携带需要会话的用户的唯一ID。连接服务器根据该唯一ID进行查询状态表,如果存在,则表示需要对话的用户在线。则直接将请求消息中转给通信服务器,通信服务器通知B用户会话请求信息,消息中携带A用户的连接信息。B接到消息之后直接对A发起一UDP数据包,消息体为空。然后B发送响应信息至通信服务器,通信服务器通知A现在可以开始与B会话。其中此处UDP与TCP使用同一端口。如果B不在线,则发送消息通知A,让其直接将信息发送至通信服务器,通信服务器负责保存本地。等B上线时再进行转发,其中保存时间可以设置。
  • 离线。A断开与连接服务器的连接。连接服务器发送命令至数据库服务器更新状态表中状态为离线。数据库服务器定时扫描状态表,并触发相应流程用于通知客户好友的上线与离线,并保证状态表的清洁。
因为上班时间写的,所以就成了草稿。回头我画下相应的图。总之,现在思路清晰了。整个系统包括以下几个台位:

  • 客户端:用于让用户接入系统
  • 注册服务器:用户接入系统时使用,提供鉴权等相应处理
  • 连接服务器:用于保持与所有用户的连接,状态消息的通知以及客户会话请求时通信服务器相关信息的返回。
  • 通信服务器:用于通信渠道的建立以及离线信息的保存。包括离线文件传输。根据实际情况可以考虑增加一台文件服务器,供通信服务器使用。
  • 数据库服务器:提供对于数据库所有的操作接口。所有关于数据库的操作均归必须通过该台位。
  • 鉴权服务器:可有可无,供注册服务器使用,主要用于鉴权。