IM服务器的架构

**一、 总的构架结构示意图: **

如上图所示,目前系统总的分成六个模块,分别为 网络/协议解析模块,用户帐号管理模块,消息处理模块,动作处理模块,数据均衡处理模块,客户状态处理模块。

正常流程应该这么实现,以一个或者几个线程运行网络/协议解析模块,然后他根据具体的包类型分发给具体的命令处理模块,每个具体的命令处理模块至少应该分别运行于不同的线程。

从上面的结构图可以看出,其中客户状态模块和网络/协议解析模块都是公用模块,其他的模块几乎都依赖于这两个模块。目前因为很多功能不予以实现,例如不实现离线消息,所以只有用户帐号管理模块跟数据库相关。

**二、 每个模块的具体功能描述 **

1. 用户帐号管理模块:
该模块管理基于用户帐号的所有操作:具体由如下:创建用户,删除用户,修改用户资料,修改用户密码,得到用户个人信息,得到好友列表,登陆,登出,请求认证串,创建群组,加入群组,离开群组。

以上所有操作,除了创建用户不需要登陆外,其他的任何操作都必须是已经登陆的用户,所以必须先有登陆操作,才能进行下一步的操作,这条规则针对所有的命令都是。

描述一下登陆过程:
客户端发送命令请求得到认证串——〉网络/协议解析模块把客户端请求以及它的用户标志转发给用户帐号管理模块——〉用户帐号管理模块自动生成一个随机认证串,同时把该客户端的用户标志一起保存在列表中(在列表中该数据只能保存一分钟,超过则删除,因此客户端必须在一分钟内利用此认证串登陆),同时把认证串由网络/协议解析模块发送给客户端——〉客户端把用户名和认证串、用户名、密码组成的新串的MD5一并发给服务器请求登陆——〉网络/协议解析模块把客户端请求以及它的用户标志转发给用户帐号管理模块——〉用户帐号管理模块首先检查列表中是否有该用户标志的数据,如果有则继续——〉从数据库中取出用户名和密码,然后从列表中取出认证串,生成MD5,看是否一致,如果一致,则表示登陆成功,服务器生成会话加密密钥,以后的所有与服务器的会话信息都采用此密钥加密和解密——〉网络/协议解析模块把结果发送给客户端,如果成功——〉网络/协议解析模块把该用户的用户标志和会话加密密钥保存在客户状态模块中。

2. 网络/协议解析模块:
网络解析模块应该保存一个最近的登陆用户列表的缓存,该列表保存的信息应该有IP和端口,还有加密密钥,最后一次访问的时间。在该列表的用户,如果超过一定时间(例如一分钟)没有访问,就要从该列表中删除。该列表的主要用途用于快速的查找登陆用户(这样频繁访问服务器的用户登录检查就不需要丛客户状态模块中查询了,提高效率),如果在此列表中查找不到,则向客户状态模块查找,如果找到了,则把用户添加到此列表中。如果找不到,则表示不在线。

任何时候收到用户的消息,则要更新登陆用户列表的缓存中的最后访问时间数据,如果该用户不在列表中,但是最后检查已经登陆,则要添加。还有心跳命令不应该影响该列表的用户数据。但是心跳命令会影响客户状态列表。

网络解析模块应该保存一个用户标志映射列表(也可以直接组合他们的数据地址),把客户端的IP地址和端口映射到一个具体的唯一客户端标志值,然后这个值以后作为这个客户端的标志,各个具体模块对客户端的任何操作都以这个标志为基础。

有四个功能
第一,根据不同的类型把数据报解密后(如果需要解密)分发给各个具体的处理模块。在分发前,首先检查该用户是否登陆,如果没有,则直接告诉客户端一个错误。对于新建用户,登陆命令,获取认证字符串的命令不需要检查是否已经登陆。
第二,自己处理相关的消息,目前自己处理的消息包括心跳消息和客户端请求建立直连的命令,还有任何数据包的格式不对或者版本不对的情况处理,则该模块自己就处理了。
第三,把用户发送消息时的状态提交给客户状态模块,其中包括用户唯一标志。如果用户在发送消息时,地址已经修改了,那么唯一标志必须保持不变,但是用户标志列表中的用户地址数据必须跟着修改。
第四,包各个模块发送给客户端的消息加密后(如果需要)处理发送给客户端。

3. 客户状态模块:
该模块的功能如下:
第一、 保存并操作所有当前在线的用户信息,包括用户的登陆时间,用户标志,用户状态(隐身等),用户帐号。提供给其他模块查询某个用户是否登陆。
第二、 处理获取在线好友的消息,如果收到此命令,则通过用户帐号管理模块查找该用的好友列表,同时查找当前的在线用户列表,然后就得到在线好友列表。
第三、 处理用户状态改变的命令,如果收到用户的状态改变消息(如登录、登出、隐身等),则查找该用户的在线好友列表,然后一一通知。
第四、 如果长时间没有收到用户的消息,则认为该用户因为意外的原因而断线,则自动认为登出。客户端在没有任何消息需要发送时,会定时的向服务器发送心跳命令,告诉服务器客户端在线,如果连续一段时间没有收到心跳信息,则认为用户已经断线。
第五、 保存并操作在线群组信息。给其他模块提供获取特定群组或者场景中的用户列表功能。

4. 消息处理模块:
处理所有的消息转发,包括群消息,好友消息。
对于好友消息,该消息处理模块首先通过客户状态模块检查好友是否在线,如果在线,则把好友消息发送过去,如果不在线,则不发送。
对于群消息,如果是针对普通的群组消息,则通过客户状态模块得到该群组的在线用户列表,然后给每个人发送该消息,除了自己。
如果是场景中的公有消息,则先检查该用户所在场景的位置,然后计算出能够听到该用户的场景中的其他用户的用户列表,然后给每个人发送消息。计算的算法参考每个场景用户的坐标,其中在特定场景中的用户不参与运算,除非在同一个的特定场景中的用户才参与运算。
注意:对于场景消息,如果客户端不是以场景方式登录的,那么就不能发送和接收场景消息。

除了以上的消息,还有广告消息,系统消息之外客户端可以接受外,陌生人不能互发消息,如果服务器接受到此列消息,必须忽略,不发送任何应答。

5. 动作处理模块:
处理所有场景动作,该消息只有场景用户方式登录的才能发送和接收动作命令。服务器接收用户的动作命令,计算出用户所在的场景中能够看到的人的列表,然后一一发送命令给该用户。计算的算法参考每个场景用户的坐标,其中在特定场景中的用户不参与运算,除非在同一个的特定场景中的用户才参与运算。

该模块中保存有一个用户的位置和动作状态表(包括是否在某个特定的场景里面信息),保存场景用户的所在场景用户的坐标和最后一次的动作状态信息。

场景用户登录后,位置每更新一次,都必须把该用户所在的场景位置坐标发送给服务器,对于心跳信息和动作信息不需要携带位置坐标数据。

6. 数据均衡处理模块:
该模块主要为了分布式处理,服务器负载平衡而设计,主要发出网络服务器重定向的命令,对于这些命令,所有客户端都必须处理,因为一旦服务器发出了这个命令后,就在此服务器不再保存该用户信息了。
目前该模块不实现。

代码交流 2021