1.dh.h
類定義概要
類名:?MySQL
功能:?簡化MySQL的連接、查詢和更新操作,提供接口給上層應用使用。
成員變量
private:MYSQL *_conn;
_conn
:指向MYSQL
結構體的指針,用于代表數據庫連接實例。由mysql_init()
初始化,之后通過mysql_real_connect
建立連接。
構造與析構函數
MySQL()
- 作用:?初始化數據庫連接對象,調用
mysql_init(nullptr)
。 - 功能:?為連接準備一個空的
MYSQL
實例。
~MySQL()
- 作用:?釋放數據庫連接資源。
- 調用:?
mysql_close(_conn)
,關閉連接,釋放資源。
成員函數(公共接口)
bool connect()
- 用途:?建立實際的數據庫連接。
- 實現細節:
- 調用
mysql_real_connect
,連接到配置信息中的數據庫(server
、user
、password
、dbname
、端口3306
)。 - 連接成功后,設置字符集為
gbk
(mysql_query(_conn, "set names gbk")
)。 - 連接成功則輸出日志“connect mysql success!”。
- 連接失敗則輸出詳細的錯誤信息,包含錯誤原因和連接參數。
- 調用
- 返回值:
true
:連接成功false
:連接失敗
bool update(string sql)
- 用途:?執行SQL更新操作(INSERT、UPDATE、DELETE等)。
- 實現細節:
- 調用
mysql_query(_conn, sql.c_str())
執行SQL。 - 若失敗,輸出錯誤,返回
false
。 - 成功返回
true
。
- 調用
- 示例:?插入新用戶或修改數據。
MYSQL_RES *query(string sql)
- 用途:?執行SQL查詢語句(SELECT),返回結果集。
- 實現細節:
- 調用
mysql_query(_conn, sql.c_str())
執行查詢。 - 若失敗,輸出錯誤信息,返回
nullptr
。 - 若成功,調用
mysql_use_result(_conn)
獲取結果集。
- 調用
- 返回值:
MYSQL_RES*
:結果集指針,調用者需負責釋放。
MYSQL* getConnection()
- 用途:?提供底層連接指針,便于更多的低級操作或調試。
- 返回:?
_conn
指針。
其他細節
連接信息存儲:
server
(127.0.0.1
)user
(root
)password
(Sf523416&111
)dbname
(chat
)
這些信息是靜態變量(
static string
),方便在整個程序中使用。日志輸出:
- 使用?
muduo/base/Logging.h
?提供的日志宏?LOG_INFO
?和?LOG_ERROR
,方便調試和監控。
- 使用?
總結
這個?MySQL
?類封裝了:
- 連接管理:?內部維護一個
MYSQL*
連接句柄。 - 連接方法:?
connect()
,連接數據庫。 - 數據操作:
update()
?執行寫操作(增刪改)。query()
?執行讀操作,返回結果集指針。
- 資源管理:?在析構函數中釋放連接。
它為上層應用提供了簡潔、封裝的數據庫訪問接口,并加入了錯誤信息輸出和日志記錄,非常適合在實際的C++服務器項目中使用。
2.FriendModel
類
讓我們一起來詳細分析這個FriendModel
類,它主要負責維護和處理好友關系相關的操作。這個類封裝了操作好友信息的兩個核心功能:添加好友關系和查詢好友列表。
類定義概述
#ifndef FRIENDMODEL_H
#define FRIENDMODEL_H#include "user.hpp"
#include <vector>
using namespace std;class FriendModel
{
public:// 添加好友關系void insert(int userid, int friendid);// 返回用戶好友列表vector<User> query(int userid);
};#endif
成員方法概述
1.?void insert(int userid, int friendid)
- 功能:?在好友關系表中插入一條新的好友關系。
2.?vector<User> query(int userid)
- 功能:?查詢某個用戶的所有好友,返回一個
User
對象的向量(好友列表)。
方法詳細解讀
1. 添加好友關系:void insert(int userid, int friendid)
實現邏輯:
- 構造SQL語句,格式為:
insert into friend values(userid, friendid)
- 創建
MySQL
對象,并連接數據庫。 - 如果連接成功,執行
update()
方法插入好友關系。
說明:
這個操作假設
friend
表有兩列(例如:userid
?和?friendid
),代表一對好友關系。
2. 查詢好友列表:vector<User> query(int userid)
實現邏輯:
構造SQL語句,使用
內部連接(inner join)
,查詢用戶的好友信息:select a.id, a.name, a.state from user a inner join friend b on b.friendid = a.id where b.userid = userid
這條語句的作用:
- 從
user
表中選出所有該用戶的好友信息。 - 通過
friend
關系表關聯用戶ID。
- 從
創建一個
vector<User>
存放好友信息。建立數據庫連接,執行查詢:
若成功,遍歷
MYSQL_RES
結果集:利用
mysql_fetch_row()
讀取每一行數據。創建一個
User
對象,設置其字段(id
、name
、state
)。將
User
加入結果向量中。
釋放
MYSQL_RES
資源。
返回好友列表
vector<User>
。
類成員變量
// 目前該類沒有顯式成員變量,只有成員方法
備注:
- 這個類設計中沒有持久的成員變量,每次操作時都新建
MySQL
對象以連接數據庫。這是一種簡單實現,適合關系不頻繁變動的場景。
其他細節
數據庫操作:
- 插入關系時調用
mysql.update(sql)
,沒有事務控制,簡單插入。 - 查詢好友信息時調用
mysql.query(sql)
,處理結果集。
- 插入關系時調用
安全性:
- 使用
sprintf
拼接SQL語句,可能存在SQL注入風險;實際應用中建議用參數化查詢。
- 使用
性能:
- 每次操作都新建數據庫連接,不復用連接,可能影響效率。
總結
這個FriendModel
類提供了兩個主要功能:
添加好友關系:
insert()
- 將兩用戶的好友關系存入數據庫。
查詢好友列表:
query()
- 根據用戶ID,查找所有好友信息,返回
User
對象的數組(好友列表)。
- 根據用戶ID,查找所有好友信息,返回
該設計結構簡潔,直接,但在性能優化和安全性方面可以進一步增強(如連接池、參數化查詢等)。
同時,它依賴于數據庫表結構(friend
表和user
表)合理設計。
3.類比FriendModel
類,還有usermodel, groupmodel,OfflinMegModel
這是數據操作模型層,負責在業務邏輯和數據存儲之間傳遞信息。它知道如何把業務需求(如添加好友)轉化為數據庫操作,也懂得如何把數據庫查詢結果轉化為業務可用的對象。
4.group.hpp,groupuser.hpp,user.hpp
?讓我們詳細分析這三個類(User
、GroupUser
、Group
)的設計與作用,它們都是典型的 ORM(對象關系映射)類,用于映射數據庫中的表結構到 C++ 對象中,方便開發中對數據的操作。
1.?User
?類(用戶基礎表的ORM類)
class User
{
public:User(int id = -1, string name = "", string pwd = "", string state = "offline"){this->id = id;this->name = name;this->password = pwd;this->state = state;}void setId(int id) { this->id = id; }void setName(string name) { this->name = name; }void setPwd(string pwd) { this->password = pwd; }void setState(string state) { this->state = state; }int getId() { return this->id; }string getName() { return this->name; }string getPwd() { return this->password; }string getState() { return this->state; }protected:int id;string name;string password;string state;
};
作用與設計:
- 表示“用戶”實體,將用戶表中的字段(
id
,?name
,?password
,?state
)映射為類成員。 - 提供了構造函數、getter、setter方法,方便操作。
- 典型的ORM類,用于在程序中封裝用戶信息。
2.?GroupUser
?類(群組用戶,擴展了User
,添加角色信息)
復制代碼
class GroupUser : public User
{
public:void setRole(string role) { this->role = role; }string getRole() { return this->role; }private:string role; // 用戶在群組中的角色(如管理員、普通成員)
};
作用與設計:
- 繼承自
User
,意味著“群組內的用戶”具有用戶的所有基本屬性(如ID、用戶名、密碼、狀態)。 - 增加
role
屬性,表示用戶在群組中的角色。 - 設計理念:一個群組中的用戶不僅僅算作普通用戶,還需區分角色,因此在群組關系中,添加了角色字段。
總結:
GroupUser
是一個“關系類”,表示某個用戶在某個群組中的身份信息(不僅僅是用戶,還包括角色屬性)。- 這樣設計方便在多對多關系中存儲角色信息(如用戶屬于哪個群,角色怎樣)。
3.?Group
?類(群組類)
class Group
{
public:Group(int id = -1, string name = "", string desc = ""){this->id = id;this->name = name;this->desc = desc;}void setId(int id) { this->id = id; }void setName(string name) { this->name = name; }void setDesc(string desc) { this->desc = desc; }int getId() { return this->id; }string getName() { return this->name; }string getDesc() { return this->desc; }vector<GroupUser> &getUsers() { return this->users; }private:int id; // 群組IDstring name; // 群組名稱string desc; // 群組描述vector<GroupUser> users; // 包含的成員列表(每個成員帶角色信息)
};
作用與設計:
- 表示“群組”實體,映射群組表。
- 含有ID、名稱、描述字段。
users
?成員變量用來存儲群組的所有成員(GroupUser
對象),實現多對多關系(一個群組有多個用戶,一用戶可能在多個群組)。- 提供了基本的getter/setter方法。
關系與整體架構理解
User
:代表整個系統的用戶信息,映射用戶表。GroupUser
:繼承用戶信息,并附加角色信息,代表某用戶在特定群組中的角色(多對多關系中的中間表/關系實體)。Group
:代表群組實體,含其成員(GroupUser
的集合)信息。
這套設計體現了面向對象方式對數據庫關系的封裝:
- 通過
Group
類管理群組信息和成員列表; - 通過
GroupUser
類描述用戶和角色之間的關系; - 通過
User
類描述用戶基礎信息。
總結:
- 這三類共同組成了一個與“群組聊天”功能相關的對象模型架構。
- 設計充分利用繼承(
GroupUser
繼承User
)來復用代碼,增強擴展性。 - 使得程序能夠以對象的方式操作數據庫中的用戶、群組與成員關系。
5.Redis
?類
這份redis.hpp
和redis.cpp
實現了一個封裝了Redis發布訂閱(Pub/Sub)功能的類,方便在C++項目中使用Redis進行消息通信。下面我會詳細介紹這個類中的成員變量和成員函數,幫助你理解它的設計思想和使用方法。
Redis
?類成員和方法詳解
1.?成員變量
復制代碼
private:redisContext *_publish_context; // 負責發布消息的上下文redisContext *_subcribe_context; // 負責訂閱消息的上下文function<void(int, string)> _notify_message_handler; // 消息接收時的回調函數
_publish_context
:用來連接和操作Redis的發布(PUBLISH
)命令,用于向頻道發送消息。_subcribe_context
:用來連接和操作Redis的訂閱(SUBSCRIBE
)命令,用于監聽和接收頻道的消息。_notify_message_handler
:業務層定義的回調函數,用于通知業務層收到的消息。
2.?構造函數和析構函數
復制代碼
Redis(); // 構造函數,初始化成員指針為空
~Redis(); // 析構函數,釋放連接
- 構造函數:初始化指針為
nullptr
。 - 析構函數:如果指針不為空,調用
redisFree()
釋放資源,避免內存泄漏。
3.?核心功能成員方法
connect()
復制代碼
bool connect();
- 連接本地Redis服務器(默認地址為?
127.0.0.1:6379
)。 - 分別創建兩個連接:一個用于發布,一個用于訂閱。
- 連接成功后,啟動一個獨立線程調用
observer_channel_message()
,不斷監聽訂閱通道中的消息,異步通知業務層。
publish()
復制代碼
bool publish(int channel, string message);
- 向指定頻道發布消息。
- 使用
redisCommand()
執行PUBLISH
命令。 - 如果成功,返回
true
,否則返回false
。
subscribe()
復制代碼
bool subscribe(int channel);
- 訂閱指定頻道。
- 使用
redisAppendCommand()
和redisBufferWrite()
向Redis服務器發出SUBSCRIBE
命令。 - 注意:訂閱操作是非阻塞的,只是發出訂閱命令,接收消息由后臺線程監聽。
unsubscribe()
復制代碼
bool unsubscribe(int channel);
- 取消訂閱某個頻道。
- 使用類似
subscribe()
的方式發出UNSUBSCRIBE
命令。
observer_channel_message()
復制代碼
void observer_channel_message();
- 運行在后臺線程中,持續調用
redisGetReply()
接收Redis服務器推送的消息。 - 解析收到的消息數組(
reply->element
):reply->element[2]->str
:消息內容reply->element[1]->str
:頻道編號
- 調用
_notify_message_handler()
通知業務層收到新消息。
init_notify_handler()
復制代碼
void init_notify_handler(function<void(int, string)> fn);
- 初始化消息通知的回調函數。
- 用戶在業務層定義處理邏輯后,調用此函數注冊。
其他細節說明
- 連接管理:在
connect()
中創建兩個redisContext
,方便分別處理發布和訂閱的連接,避免競爭和阻塞。 - 多線程:
- 訂閱消息的監聽在
observer_channel_message()
中運行在單獨的線程,保證異步處理。
- 訂閱消息的監聽在
- 內存管理:
- 使用
freeReplyObject()
釋放redisReply
資源。
- 使用
- 命令執行:
- 發布:
redisCommand()
- 訂閱/取消訂閱:
redisAppendCommand()
?+?redisBufferWrite()
,避免阻塞調用。
- 發布:
- 錯誤處理:
- 連接失敗和命令失敗都輸出錯誤信息,返回
false
。
- 連接失敗和命令失敗都輸出錯誤信息,返回
總結:
這個Redis
類封裝了Redis的Pub/Sub基本操作:
- 連接:
connect()
- 發布消息:
publish()
- 訂閱頻道:
subscribe()
- 取消訂閱:
unsubscribe()
- 異步監聽消息:在后臺線程中自動調用
observer_channel_message()
,收到消息后通過回調通知業務邏輯。 - 回調機制:用戶可以注冊自己的消息處理函數。
它實現了異步訂閱模型,能很好地應用在類似聊天服務器、實時通知等場景,非常實用。
6.ChatServer類
你的代碼基于知名的?Muduo?網絡庫,實現了一個高效、易維護的聊天服務器主控類。下面按照結構–成員變量–成員方法詳細分析:
一、ChatServer 類的結構作用
ChatServer 封裝了實際的網絡服務器邏輯,負責:
- 初始化服務器、設置參數
- 監聽和管理客戶端連接
- 管理消息收發和業務處理
- 調度事件循環(事件驅動)
二、成員變量講解
private:TcpServer _server; // 組合muduo庫,實現服務器功能的類對象EventLoop *_loop; // 指向事件循環對象(相當于主線程的事件分發器)
1.?TcpServer _server
- Muduo 中封裝的 TCP 服務器核心類。
- 能自動監聽端口,負責底層 epoll、多線程 I/O、連接管理等“苦力活”。
- ChatServer 通過它實現與客戶端的所有網絡交互。
2.?EventLoop *_loop
- 事件循環指針。
- 實際上是主 Reactor 的事件分發器,用于響應 I/O 事件。
三、成員方法詳解
構造函數:ChatServer(EventLoop*, const InetAddress&, const string&)
ChatServer(EventLoop *loop, const InetAddress &listenAddr, const string &nameArg): _server(loop, listenAddr, nameArg), _loop(loop)
{// 注冊鏈接回調_server.setConnectionCallback(std::bind(&ChatServer::onConnection, this, _1));// 注冊消息回調_server.setMessageCallback(std::bind(&ChatServer::onMessage, this, _1, _2, _3));// 設置線程數量_server.setThreadNum(4);
}
作用總結與細節分析:
- 初始化?
_server
,告訴 muduo 用哪臺主機 IP/端口監聽(listenAddr
)、取什么名字(nameArg
)、用哪個 event loop。 setConnectionCallback()
:綁定"有新連接/斷開"時執行?onConnection
?方法。setMessageCallback()
:綁定"收到消息"時執行?onMessage
?方法。setThreadNum(4)
:用 4 個工作線程處理 I/O,提升吞吐量。
void start()
void ChatServer::start()
{_server.start();
}
- 真正地啟動服務器(讓 Muduo 開始監聽并接收客戶端連接)。
void onConnection(const TcpConnectionPtr&)
void ChatServer::onConnection(const TcpConnectionPtr &conn)
{// 客戶端斷開鏈接if (!conn->connected()){ChatService::instance()->clientCloseException(conn);conn->shutdown();}
}
核心作用:
- 這是連接狀態變化時的回調(新連接或斷開)。
- 如果連接斷開,則做以下處理:
- 通知業務服務層進行賬號、數據等“下線”處理(
clientCloseException
)。 - 主動關閉 socket(
conn->shutdown()
)。
- 通知業務服務層進行賬號、數據等“下線”處理(
void onMessage(const TcpConnectionPtr&, Buffer *, Timestamp)
void ChatServer::onMessage(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp time)
{string buf = buffer->retrieveAllAsString();try {json js = json::parse(buf);// 檢查必須字段if (!js.contains("msgid")) {throw json::exception("Missing 'msgid' field");}auto msgHandler = ChatService::instance()->getHandler(js["msgid"].get<int>());msgHandler(conn, js, time);}catch (const json::exception& e) {LOG_ERROR << "JSON parse error: " << e.what();if (conn->connected()) {json response;response["msgid"] = INVALID_MSG_ACK;response["errno"] = 400;response["errmsg"] = "Invalid JSON format: " + string(e.what());conn->send(response.dump());}}catch (const exception& e) {LOG_ERROR << "Message handling error: " << e.what();}
}
詳細流程:
- 拿到完整緩沖區數據(收到的一次消息)。
- 嘗試解析為 JSON 對象。
- 檢查是否有"msgid"字段(決定了本消息應該怎么處理)。
- 調用 ChatService::instance()->getHandler(msgid) 找到對應業務處理函數,然后把消息傳給它執行。
- 如果解析失敗/消息結構有誤,則:
- 打日志報錯
- 給客戶端返回錯誤提示
作用通俗理解:
“服務器收到客戶發來的消息,把這消息當成快遞包裹拆開看——快遞單上寫著包裹類型(msgid),然后根據類型分給對應員工(handler)處理。拆快遞出錯就寫個反饋單還回去。”
四、補充說明
成員方法之間的關系
- start?用于啟動服務器。
- onConnection/onMessage?并不是主動調用,而是事件驅動,在有連接/消息時被 Muduo 框架自動調用。
- 事件響應機制和reactor思想一致。
和 ChatService 的協作
ChatServer 只管網絡部分,具體業務如何處理交由 ChatService,“專人專職”,大大降低耦合。
五、總結
ChatServer 核心成員&方法概覽:
名稱 | 簡要作用 |
---|---|
_server | Muduo 的 TCP 服務器,負責監聽和通信。 |
_loop | 名字叫event loop,事件派發中心。 |
start() | 啟動服務器。 |
onConnection() | 檢測連接/斷開,并在斷開時交給業務進一步下線處理。 |
onMessage() | 收到客戶端數據時解析json,根據業務類型分發給具體handler處理;出問題自動回錯。 |
構造函數 | 初始化服務器參數并注冊各回調,每一步都讓ChatServer做最擅長的事情。 |
這樣,不僅代碼結構清晰,而且便于擴展和維護,是高性能網絡服務推薦的模式!
7.chatservice類
會把這個ChatService
類中的所有成員變量和方法,逐個詳細講解,確保你理解每個部分的作用、設計思想以及它們的工作流程,而且會盡力用通俗易懂的語言,讓你像聽故事一樣理解這個“聊天服務”系統。
一、類的整體架構和角色定位
ChatService
是一個“聊天服務器”的核心業務類(管理者)。它采用單例模式(確保整個程序中只存在唯一的實例),負責處理所有的“用戶登錄、注冊、點對點聊天、群聊、好友關系、群組操作”等業務邏輯。
二、成員變量(這個類內部存的“存儲空間”和“工具箱”)
1.?單例實例
static ChatService *instance();
- 作用:提供調用的入口,用于獲取或創建唯一的
ChatService
實例(即單例設計模式)。 - 通俗理解:就像超市只有一個“管理員”實例,這個方法幫你拿到它。
2.?消息處理映射表
unordered_map<int, MsgHandler> _msgHandlerMap;
- 作用:把不同“消息ID”映射到對應“處理函數”。
- 比如:
登錄
對應login()
函數,注冊
對應reg()
函數。 - 通俗理解:就像菜單點菜表,點“牛排”就知道要做牛排一樣。
3.?在線用戶連接表
unordered_map<int, TcpConnectionPtr> _userConnMap;
- 作用:存放已登錄、在線用戶的“用戶ID”和“對應的TCP連接指針”。
- 用途:當需要向某用戶發消息時,先找這個表看用戶是否在線,在線了就可以直接推送消息。
- 通俗理解:像“電話簿”,存著每個誰在線、用哪個電話(連接)。
4.?連接互斥鎖
mutex _connMutex;
- 作用:在多線程環境下,保證對
_userConnMap
的操作(增刪改查)是安全的。 - 為何需要:因為可能有多個連接同時操作這個表,比如一個用戶剛登錄、登出,或服務器在同時處理多個請求。
5.?數據模型對象(操作數據庫)
復制代碼
UserModel _userModel;
OfflineMsgModel _offlineMsgModel;
FriendModel _friendModel;
GroupModel _groupModel;
- 作用:封裝了數據庫操作的封裝類(操作用戶信息,離線消息,好友關系,群組信息)。
- 例子:
_userModel
:查詢或更新用戶信息。_offlineMsgModel
:存儲或讀取離線消息。_friendModel
:管理好友關系(添加好友等)。_groupModel
:管理群聊信息。
6.?Redis操作對象
復制代碼
Redis _redis;
- 作用:封裝了與Redis(一個高速的數據庫和消息隊列系統)的交互,用于實現“跨進程”、“多服務器”的消息推送和訂閱。
三、主要方法(業務邏輯執行的“技能”)
1.?獲取單例實例
復制代碼
static ChatService *instance();
- 作用:返回全局唯一的
ChatService
對象,確保程序中只有一個“聊天服務”。 - 實現:用“靜態局部變量”,保證只創建一次。
2.?構造函數(注冊消息-handler)
復制代碼
ChatService::ChatService()
- 作用:
- 初始化各種消息ID和對應的請求處理函數的映射關系。
- 鏈接(連接)Redis,為后續消息訂閱做準備。
注冊消息響應(通過bind
綁定對應成員函數)
login
注冊到LOGIN_MSG
register
注冊到REG_MSG
oneChat
注冊到ONE_CHAT_MSG
還有好友添加、創建群、加入群、群聊的處理方法。
通俗理解:像打電話時撥通不同號碼調用不同小姐姐的服務。
3.?業務重置(重要)
復制代碼
void reset();
- 作用:
- 在服務器異常或重啟時調用。
- 將所有“已登錄的用戶”狀態重置為“離線”狀態(確保狀態同步真實情況)。
- 調用場景:系統崩潰后,恢復正常工作狀態。
4.?獲取特定“消息類型”對應的處理函數
復制代碼
MsgHandler getHandler(int msgid);
- 作用:
- 輸入
msgid
,返回對應的處理函數(函數指針或lambda)。 - 如果找不到,就返回一個“錯誤處理器”。
- 輸入
- 設計亮點:
- 動態路由:前端發的不同消息會被路由到不同的處理函數去。
5.?各類具體業務的處理方法(詳細講解)
login()登陸流程
- 輸入:用戶ID、密碼。
- 邏輯:-查詢用戶信息,驗證密碼。-用戶已在線,提示重復登錄,否則:-存用戶名和連接關系到
_userConnMap
,方便推送。-在Redis訂閱頻道(方便跨服務通知)。-更新用戶狀態為在線。-返回用戶信息(包括離線消息、好友列表、群組信息)。 - 作用:實現實際“登陸”功能。
reg()注冊
- 輸入:用戶名、密碼。
- 邏輯:-校驗格式、長度。-存入數據庫。-返回成功或失敗。
loginout()退出/注銷
- 作用:-從活躍連接中刪除用戶。-在Redis取消訂閱某渠道(讓其他服務器知道該用戶已離線)。-更新數據庫用戶狀態。
clientCloseException()
- 作用:
- 處理客戶端異常斷開連接(比如突然關閉窗口,沒有正常退出)。
- 類似
loginout
,清除連接,更新狀態。
oneChat()點對點聊天
- 輸入:接收方
toid
,消息內容。 - 機制:-第一步:找
_userConnMap
,看看對方是否在線(直接推)。-第二步:如不在線,則存離線消息。-第三步:如果對方在線但不在自己服務器(假設多節點),就用Redis發布消息,其他節點會收信息。
addFriend()添加好友
- 輸入:自己ID和好友ID。
- 操作:存入好友關系表。
createGroup()
- 輸入:發起人ID、群組名、描述。
- 操作:-在數據庫中創建新群。-將發起人加入該群(權限設為“creator”)。
addGroup()加入群組
- 輸入:用戶ID、群ID。
- 操作:將用戶加入群組。
groupChat()群聊
- 輸入:群ID、群成員消息。
- 作用:
- 中轉消息:
- 先找成員在不在線(在自己連接map里)。
- 在線了推送。
- 不在線存離線消息(存到數據庫中)。
- 中轉消息:
6.?處理Redis訂閱消息
復制代碼
void handleRedisSubscribeMessage(int, string);
- 作用:
- 其他服務器發布同步消息后,調用此函數。
- 找到對應的用戶連接,如果在,推送消息。
四、重點總結(通俗版)
ChatService
就像一個“指揮官”,協調所有聊天相關的操作。- 存放“用戶和連接關系”,方便主動“發消息給用戶”。
- 有事注冊“事件處理器”:不同的ID對應不同操作(登錄、注冊、聊天、群聊)。
- 利用Redis實現多服務消息同步。
- 每個業務都是封裝好的函數:登錄、注冊、點對點聊天等。
- 整體設計高擴展性、線程安全、結構清晰。