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爲羣聊窗口。在羣聊窗口中能夠接收到打開了該窗口的其餘用戶發送的聊天信息。同時本身也能輸入相關聊天消息併發送給全部該窗口下的其餘用戶。

相關文章
相關標籤/搜索