云计算百科
云计算领域专业知识百科平台

集群聊天服务器各个类进行详解

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对象的数组(好友列表)。
  • 该设计结构简洁,直接,但在性能优化和安全性方面可以进一步增强(如连接池、参数化查询等)。

    同时,它依赖于数据库表结构(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; // 群组ID
    string 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实现多服务消息同步。
    • 每个业务都是封装好的函数:登录、注册、点对点聊天等。
    • 整体设计高扩展性、线程安全、结构清晰。
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 集群聊天服务器各个类进行详解
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!