C++服务器设计(七):聊天系统服务端实现

  在以前的章节中,咱们对服务端系统的设计实现原理进行了剖析,在这一章中,咱们将对服务端框架进行实际运用,实现一款运行于内网环境的聊天系统。该聊天系统由客户端与服务器两部分组成,同时服务端经过数据库维护用户的帐号信息。本章将重点介绍如何运用该服务端框架进行服务器业务逻辑开发。sql

聊天系统功能分析

  本聊天系统只做为服务端框架的运用展现,所以仅限于最基本的局域网聊天工具,数据传输均采用为明文形式,并不在安全性上进行深刻探讨。具体功能需求分析以下:数据库

  • l  用户注册:提供新用户帐号注册功能,注册内容包括新用户的帐号名和密码。服务器须要检测注册信息的有效性,并将注册用户的信息保存在数据库中。
  • l  用户登陆:用户根据帐号密码进行登陆操做,若未进行登陆操做将无权限请求聊天相关消息。服务器查询数据库验证用户帐号信息,同时判断该用户是否已经登录。用户帐号不容许重复登陆。
  • l  在线好友更新:已登陆用户能够主动向服务器查询当前在线的好友信息。服务器一样应该及时向全部登陆用户推送好友上线及下线信息。
  • l  好友聊天:已登陆用户能够向在线状态的任意好友发送聊天消息,同时也能接收到来自其余在线状态的好友发送过来的消息。
  • l  群体聊天:已登陆用户能够同时向全部在线状态的好友发送群体聊天消息。同时也能接收到来自其余在线状态的好友发送的群体聊天消息。

聊天系统服务端实现

数据库实现

  聊天系统须要维护用户的帐号信息,记录注册的新帐号,并对每次登陆的用户信息进行校验。咱们选用轻量级的Mysql做为数据库管理系统,并选择Mysql++做为Mysql的API操做库。安全

  整个聊天系统只创建了一个名为UserInfo表结构,如表5-1所示。同时根据Mysql++封装了两个操做接口,分别添加新用户帐号信息,以及根据帐号名和密码查询该用户是否存在。服务器

表5-1 用户帐号信息表UserInfo网络

字段名并发

数据类型框架

关键字异步

约束工具

含义spa

id

int(20)

Y

unique

惟一标识符

username

varchar(20)

N

unique,not null

帐号名

Password

varchar(20)

N

not null

密码

  因为数据库操做涉及网络传输及磁盘处理,所以属于耗时操做。而在服务端框架Reactor反应池中的全部处理必须在非阻塞环境下进行,若是进行耗时操做将会阻塞当前线程,致使其它消息事件得不到及时处理。所以在Reactor中进行数据库操做应该以异步的方式进行,能够经过建立工做线程池的方式处理数据库等耗时操做。可是在本聊天系统中,只有在注册新用户和用户登陆两个场景中才涉及数据库操做。为了简化开发模型,咱们在此直接调用数据库相关的操做。

  数据库部分并不是本文论述重点,所以再也不作进一步介绍。

聊天设备类型及消息事件实现

  经过分析功能需求,能够得知客户端链接主要存在两种状态下的消息请求,分别为临时状态和登陆状态。在临时状态下须要可以请求注册新用户和登陆操做,在登陆状态下须要可以请求当前在线用户信息,向某个用户发送消息类型和广播消息类型。而且因为服务器存在登陆超时的机制,客户端链接无论在临时状态仍是登陆状态,均需定时向服务器发送心跳消息。

  客户端的两种状态正好对应于服务端框架制定的两种设备类型,即临时设备类型和登陆设备类型。如图5-1所示。咱们为临时设备添加新的注册帐号消息事件,用于向全部与服务端创建了链接的客户进行注册操做。同时咱们建立一个新的设备类型,名为ChatType设备类型,而且继承于登陆设备类型,用于专门处理登陆后和聊天相关的消息事件。

 

图5-1 聊天设备类型及消息事件

  临时设备类型新添加的消息事件介绍以下:

  • l  registerUsr:注册新的用户帐号。客户端在请求该消息事件时需同时传入期待注册的帐号名和密码。服务器接收到该消息事件后,将校验帐号名和密码是否合法,而后调用数据库新帐户注册接口,进行帐户注册。最后根据数据库实际插入结果向客户端发送注册结果信息。因为该消息事件无需请求权限,任何链接该服务器的客户都可进行注册操做。为了防止存在某些客户进行恶意注册现象,在实际实现中添加了邀请码信息。服务端将会验证客户端传来的邀请码是否正确,若是邀请码正确才会实际进行注册操做。
  • l  heartMsg:心跳消息。客户端将会按期发送心跳消息。服务器接收到该消息事件后,将会在超时队列更新该链接的超时信息。在事件回调实现中,并不会对该消息进行进一步业务处理,而是直接返回。

 

  ChatType为新建立的继承于默认登陆设备的设备类型,具体实现的消息事件介绍以下:

  • l  askFriends:请求当前在线的用户信息。客户端会在登陆成功后,向服务器请求该消息事件。服务器收到该消息事件后,将会查询除请求者外,当前其余全部在线的ChatType类型的用户信息,并整理发送给客户端。该数据用于客户端对在线用户列表的初始化工做。
  • l  chatSend:向一个指定在线用户发送聊天消息。客户端将会把聊天消息的内容,本身的信息,及指望接收该聊天消息的用户信息发送给服务器。服务端接收到该消息事件后,将会尝试找寻该接收用户,并将聊天消息和发送者消息转发给该接收用户,并向发送用户返回发送成功消息事件。若是该接收用户并不在线,将只会向发送用户返回发送失败的消息事件。
  • l  groupSend:向全体在线用户发送聊天消息。客户端将会把聊天消息及自身信息发送给服务器。服务器接收到该消息后,将会遍历除请求者外,当前其余全部在线的ChatType类型的用户,并将该聊天消息和发送者信息转发给全部遍历的用户,并向发送用户返回发送成功的消息。
  • l  heartMsg:心跳消息。同临时设备新添加的heartMsg的心跳消息。

聊天设备的生命周期实现

  虽然咱们已经为聊天客户端的链接制定了具体的设备类型和消息事件,可是一些和链接状态相关的业务逻辑仍然须要咱们设计。好比如何制定与聊天客户端相关的具体登陆过程?当某个聊天客户端已经成功登陆后,怎样第一时间通知其余客户端该帐号已上线?当某个聊天客户端退出时,又如何通知其余客户端该帐号已下线?这些与客户端状态相关的操做都依赖上一章节制定的链接生命周期机制来进行管理。

 

图5-2 聊天设备的生命周期

  具体的聊天设备的链接生命周期实现如图所示。咱们只需对具体业务相关的生命周期接口的实现进行重写便可,所以无需进行更改的生命周期接口并未被列出。须要被重写的接口实现介绍以下:

  • l  onLoginCheckMsg():当客户端执行登陆操做,且选择登陆类型为ChatType设备类型时,将会执行该接口。此时系统将会检查客户端传来的帐号名和密码是否合法,若是合法将会调用数据库的帐号密码查询接口,判断该帐户是否存在。若是该帐户存在,则返回True,并将控制权交还给系统进行进一步的登陆操做;若是该帐户不存在,则向该客户端发送不存在该帐号信息,这次登陆失败的消息,并直接返回False退出整个登陆操做。
  • l  onLoginSuccessMsg():当登陆类型为ChatType的客户端进行登陆操做,执行onLoginCheckMsg()返回True,且系统整个登陆过程成功时,将会执行该接口。此时系统将会进行两件工做:首先向该客户端发送登陆成功的消息;其次将会遍历除该用户自己外的其余已登陆的ChatType类型的用户,并向这些用户发送通知消息代表该新用户已上线。这样每一个登陆用户只需在第一次登陆的时候向服务器请求当前全部在线用户信息,而新的用户上线或老用户下线等信息将由服务器主动推送,而无需客户端按期请求维护。
  • l  onLoginFailureMsg():当登陆类型为ChatType的客户端进行登陆操做,执行onLoginCheckMsg()返回True,但整个登陆过程失败时,将会执行该接口。通常该接口被执行将代表此用户帐号已经被登陆,服务器没法对相同帐号进行重复登陆操做。此时服务器将会向客户端发送重复登陆,这次登陆失败的消息,并退出整个登陆操做。
  • l  onLogoutMsg():当登陆类型为ChatType的客户端进行注销操做时,将会执行该接口。服务器将向该客户端返回注销成功的消息,并对该链接进行进一步的注销操做。
  • l  releaseConnNode():当登陆类型为ChatType的客户端进行注销成功,或者链接因为超时或者其它异常缘由被迫退出时,将会执行该接口。此时服务器将会遍历除该用户自己外的其余已登陆的ChatType类型的用户,并向这些用户发送通知消息代表该用户已经下线。同时系统将会把该用户链接所申请的相关资源进行释放工做。
  • l  onOverTime():当服务器一段时间内未收到该客户端有效消息或心跳消息,将会被判超时,并执行该接口。通常执行该接口时代表该客户端已经因为异常而中止工做,可是并未主动断开链接。此时服务器将尝试向该客户端发送一条该链接已经超时的消息。因为客户端已经处于异常状态,并不能保证该条消息可以被客户端接收。而后服务器将会执行releaseConnNode()接口,并强制断开该客户端链接。

聊天系统展现

  该聊天系统部署于局域网内,并可经过C#实现的客户端进行相关操做。运行场景截图以下:

图5-3 登陆及注册窗口

  如图5-3为客户端的登陆窗口与注册窗口。注册窗口经过登陆窗口的注册按键打开,并可进行新帐号的注册操做。同时登陆窗口能够进行帐号的登陆操做,若是登陆失败将会显示具体失败缘由;若是登陆成功,将会进入客户端主界面。

 

图5-4 主界面及好友聊天窗口

  如图5-4为客户端的主界面及聊天窗口。在主界面中显示了当前登陆的用户名及当前在线的用户名列及数量。能够单击具体用户名进入与该用户的聊天窗口。在聊天窗口中,能够在输入栏输入消息,并点击发送键或按下回车键发送该消息。若是收到其余用户的聊天消息,客户端也会主动弹出该用户的聊天窗口,并显示接收的的聊天信息。在主界面的下方还存在群聊按键,点击能够进入群聊窗口。

 

图5-5 群聊窗口

  如图5-5为群聊窗口。在群聊窗口中能够接收到打开了该窗口的其余用户发送的聊天信息。同时本身也能输入相关聊天消息并发送给全部该窗口下的其余用户。

相关文章
相关标签/搜索