【消息队列项目】连接管理模块实现

目录

[一.Connection类 - 连接实例](#一.Connection类 - 连接实例)

[二 ConnectionManager类 - 连接集中管理](#二 ConnectionManager类 - 连接集中管理)

[三. 工作流程详解](#三. 工作流程详解)

四.代码总结

五.代码测试


本模块采用两级管理体系实现网络连接的高效管理。

  • 顶层为连接管理器(ConnectionManager),负责全局连接的注册与生命周期管理;
  • 底层为Connection连接对象(Connection),封装单个物理连接并提供逻辑信道的多路复用能力。

每个Connection对象基于Muduo网络库的TcpConnection实现,内置Protobuf协议编解码器、消费者管理器、虚拟机主机环境以及线程池资源,能够在一个物理连接上创建多个独立的逻辑信道,实现业务流隔离与资源复用。

一.Connection类 - 连接实例

职责:

管理单个TCP连接的完整生命周期,提供信道创建、关闭与检索功能,处理连接级别的协议交互。

核心成员:

  • 连接关联的信道管理句柄(实现信道的增删查)
  • 连接关联的实际用于通信的muduo::net::Connection连接
  • protobuf 协议处理的句柄(ProtobufCodec对象)
  • 消费者管理句柄:管理消息消费逻辑,将协议消息路由到对应的业务处理器
  • 虚拟机管理句柄:关联的虚拟主机实例,提供业务执行环境
  • 异步线程池句柄:用于执行耗时的业务处理任务,避免阻塞网络I/O线程

信道管理接口

  • openChannel():根据请求创建新信道,验证信道ID唯一性,初始化信道资源与回调,向客户端返回创建结果
  • closeChannel():关闭指定信道,清理信道相关资源,通知客户端关闭完成
  • getChannel():根据信道ID检索已建立的信道
  • basicResponse():生成标准响应消息,统一设置请求ID、信道ID和操作结果,通过协议编解码器发送至客户端

根据上述涉及,我们很快就能写出下面这个代码

cpp 复制代码
// Connection类:管理单个TCP连接,提供信道的创建、关闭和查询功能
class Connection { 
public: 
    using ptr = std::shared_ptr<Connection>;  // 智能指针别名,便于资源管理
    
    // 构造函数:初始化连接所需的各个组件
    Connection(const VirtualHost::ptr &host,       // 虚拟机主机环境
               const ConsumerManager::ptr &cmp,    // 消费者管理器
               const ProtobufCodecPtr &codec,      // Protobuf协议编解码器
               const muduo::net::TcpConnectionPtr &conn,  // 底层TCP连接
               const threadpool::ptr &pool);       // 工作线程池
    
    // 打开信道:处理客户端打开信道的请求
    void openChannel(const openChannelRequestPtr &req);
    
    // 关闭信道:处理客户端关闭信道的请求
    void closeChannel(const closeChannelRequestPtr &req);
    
    // 获取信道:根据信道ID查找对应的信道对象
    Channel::ptr getChannel(const std::string &cid);
    
private: 
    // 基础响应函数:构造并发送标准的响应消息
    void basicResponse(bool ok, const std::string &rid, const std::string &cid);
    
private: 
    muduo::net::TcpConnectionPtr _conn;   // 底层TCP连接对象
    ProtobufCodecPtr _codec;              // Protobuf协议编解码器
    ConsumerManager::ptr _cmp;            // 消费者管理器,用于消息路由
    VirtualHost::ptr _host;               // 虚拟机主机环境
    threadpool::ptr _pool;                // 异步工作线程池
    ChannelManager::ptr _channels;        // 信道管理器,管理本连接的所有信道
}; 

这个类还是很简单就能实现的

cpp 复制代码
// Connection类:管理单个TCP连接,提供信道的创建、关闭和查询功能
class Connection { 
public: 
    using ptr = std::shared_ptr<Connection>;  // 智能指针别名,便于资源管理
    
    // 构造函数:初始化连接所需的各个组件
    Connection(const VirtualHost::ptr &host,       // 虚拟机主机环境
               const ConsumerManager::ptr &cmp,    // 消费者管理器
               const ProtobufCodecPtr &codec,      // Protobuf协议编解码器
               const muduo::net::TcpConnectionPtr &conn,  // 底层TCP连接
               const ThreadPool::ptr &pool)        // 工作线程池
        : _conn(conn), _codec(codec), _cmp(cmp), 
          _host(host), _pool(pool), 
          _channels(std::make_shared<ChannelManager>()) {}  // 创建信道管理器
    
    // 打开信道:处理客户端打开信道的请求
    void openChannel(const openChannelRequestPtr &req) { 
        // 1. 尝试创建信道,检查信道ID是否重复
        bool ret = _channels->openChannel(req->cid(), _host, _cmp, _codec, _conn, _pool);
        if (ret == false) { 
            // 创建失败,记录日志并返回错误响应
            DLOG("创建信道的时候,信道ID重复了"); 
            return basicResponse(false, req->rid(), req->cid()); 
        } 
        
        // 2. 创建成功,记录日志
        DLOG("%s 信道创建成功!", req->cid().c_str()); 
        
        // 3. 返回成功响应给客户端
        return basicResponse(true, req->rid(), req->cid()); 
    } 
    
    // 关闭信道:处理客户端关闭信道的请求
    void closeChannel(const closeChannelRequestPtr &req) { 
        // 关闭指定信道
        _channels->closeChannel(req->cid()); 
        // 返回成功响应给客户端
        return basicResponse(true, req->rid(), req->cid()); 
    } 
    
    // 获取信道:根据信道ID查找对应的信道对象
    Channel::ptr getChannel(const std::string &cid) { 
        return _channels->getChannel(cid); 
    } 
    
private: 
    // 基础响应函数:构造并发送标准的响应消息
    void basicResponse(bool ok, const std::string &rid, const std::string &cid) { 
        basicCommonResponse resp;        // 创建响应消息对象
        resp.set_rid(rid);              // 设置请求ID
        resp.set_cid(cid);              // 设置信道ID
        resp.set_ok(ok);                // 设置操作结果(成功/失败)
        _codec->send(_conn, resp);      // 通过编解码器发送响应
    } 
    
private: 
    muduo::net::TcpConnectionPtr _conn;   // 底层TCP连接对象
    ProtobufCodecPtr _codec;              // Protobuf协议编解码器
    ConsumerManager::ptr _cmp;            // 消费者管理器,用于消息路由
    VirtualHost::ptr _host;               // 虚拟机主机环境
    ThreadPool::ptr _pool;                // 异步工作线程池
    ChannelManager::ptr _channels;        // 信道管理器,管理本连接的所有信道
}; 

二 ConnectionManager类 - 连接集中管理

职责:

作为连接管理的单例或全局管理器,维护所有活跃连接的注册表,确保连接资源的正确分配与回收。

核心机制:

  • 线程安全容器:使用互斥锁保护的哈希表存储连接映射
  • 连接标识:以Muduo的TcpConnectionPtr作为连接的唯一键值
  • 自动清理:连接断开时自动从管理器中移除

关键接口:

newConnection():注册新建立的连接

  1. 检查连接是否已存在(防止重复注册)
  2. 创建Connection对象并建立完整资源链
  3. 将连接加入全局管理映射表

delConnection():移除已断开的连接

  • 从管理映射表中擦除连接记录
  • 触发连接对象的析构与资源释放
  • 连接检索功能

getConnection():根据底层连接句柄查找对应的Connection对象

  • 线程安全的查找操作
  • 返回智能指针,支持空值表示连接不存在

这个类还是很简单的,所以我们直接就写出来了

cpp 复制代码
// ConnectionManager类:全局连接管理器,负责所有连接的生命周期管理
class ConnectionManager { 
public: 
    using ptr = std::shared_ptr<ConnectionManager>;  // 智能指针别名
    
    ConnectionManager() {}  // 默认构造函数
    
    // 创建新连接:当新的TCP连接建立时调用此函数
    void newConnection(const VirtualHost::ptr &host,       // 虚拟机主机环境
                       const ConsumerManager::ptr &cmp,    // 消费者管理器
                       const ProtobufCodecPtr &codec,      // Protobuf协议编解码器
                       const muduo::net::TcpConnectionPtr &conn,  // 底层TCP连接
                       const ThreadPool::ptr &pool)// 工作线程池 
    {
        std::unique_lock<std::mutex> lock(_mutex);  // 加锁,保证线程安全
        
        // 检查连接是否已存在(防止重复添加)
        auto it = _conns.find(conn);
        if (it != _conns.end()) 
        { 
            return ;  // 连接已存在,直接返回
        } 
        
        // 创建新的Connection对象
        Connection::ptr self_conn = std::make_shared<Connection>(host, cmp, codec, conn, pool);
        
        // 将新连接添加到连接映射表中
        _conns.insert(std::make_pair(conn, self_conn));
    } 
    
    // 删除连接:当TCP连接断开时调用此函数
    void delConnection(const muduo::net::TcpConnectionPtr &conn) { 
        std::unique_lock<std::mutex> lock(_mutex);  // 加锁,保证线程安全
        _conns.erase(conn);  // 从连接映射表中删除指定连接
    } 
    
    // 获取连接:根据底层TCP连接对象查找对应的Connection对象
    Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn) { 
        std::unique_lock<std::mutex> lock(_mutex);  // 加锁,保证线程安全
        
        auto it = _conns.find(conn);  // 查找连接
        if (it == _conns.end()) { 
            return Connection::ptr();  // 连接不存在,返回空指针
        } 
        
        return it->second;  // 返回找到的连接对象
    } 
    
private: 
    std::mutex _mutex;  // 互斥锁,保护连接映射表的线程安全访问
    
    // 连接映射表:key为底层TCP连接对象,value为对应的Connection对象
    std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _conns;
}; 

三. 工作流程详解

3.1 连接建立流程

  • 客户端建立TCP连接,Muduo网络库创建TcpConnection
  • ConnectionManager收到新连接通知,调用newConnection()
  • 管理器创建Connection对象,传入所有必要的依赖组件
  • 连接被注册到全局映射表,完成初始化

3.2 信道创建流程

  • 客户端发送openChannelRequest请求
  • Connection的openChannel()方法被调用
  • 信道管理器检查请求中的信道ID是否重复
  • 若ID可用,创建新信道并配置完整的处理链
  • 生成响应消息,通过协议编解码器发送回客户端

3.3 连接关闭流程

  • 检测到TCP连接断开或收到关闭请求
  • ConnectionManager调用delConnection()移除连接
  • 连接对象的所有信道被自动清理
  • 关联的虚拟机资源、消费者等组件被安全释放

四.代码总结

注意我们的代码都是存放在下面这个connection.hpp里面的

cpp 复制代码
#include "channel.hpp"

namespace mymq
{

    // Connection类:管理单个TCP连接,提供信道的创建、关闭和查询功能
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>; // 智能指针别名,便于资源管理

        // 构造函数:初始化连接所需的各个组件
        Connection(const VirtualHost::ptr &host,             // 虚拟机主机环境
                   const ConsumerManager::ptr &cmp,          // 消费者管理器
                   const ProtobufCodecPtr &codec,            // Protobuf协议编解码器
                   const muduo::net::TcpConnectionPtr &conn, // 底层TCP连接
                   const ThreadPool::ptr &pool)              // 工作线程池
            : _conn(conn), _codec(codec), _cmp(cmp),
              _host(host), _pool(pool),
              _channels(std::make_shared<ChannelManager>())
        {
        } // 创建信道管理器

        // 打开信道:处理客户端打开信道的请求
        void openChannel(const openChannelRequestPtr &req)
        {
            // 1. 尝试创建信道,检查信道ID是否重复
            bool ret = _channels->openChannel(req->cid(), _host, _cmp, _codec, _conn, _pool); // 直接创建信道
            if (ret == false)
            {
                // 创建失败,记录日志并返回错误响应
                DLOG("创建信道的时候,信道ID重复了");
                return basicResponse(false, req->rid(), req->cid());
            }

            // 2. 创建成功,记录日志
            DLOG("%s 信道创建成功!", req->cid().c_str());

            // 3. 返回成功响应给客户端
            return basicResponse(true, req->rid(), req->cid());
        }

        // 关闭信道:处理客户端关闭信道的请求
        void closeChannel(const closeChannelRequestPtr &req)
        {
            // 关闭指定信道
            _channels->closeChannel(req->cid());
            // 返回成功响应给客户端
            return basicResponse(true, req->rid(), req->cid());
        }

        // 获取信道:根据信道ID查找对应的信道对象
        Channel::ptr getChannel(const std::string &cid)
        {
            return _channels->getChannel(cid);
        }

    private:
        // 基础响应函数:构造并发送标准的响应消息
        void basicResponse(bool ok, const std::string &rid, const std::string &cid)
        {
            basicCommonResponse resp;  // 创建响应消息对象
            resp.set_rid(rid);         // 设置请求ID
            resp.set_cid(cid);         // 设置信道ID
            resp.set_ok(ok);           // 设置操作结果(成功/失败)
            _codec->send(_conn, resp); // 通过编解码器发送响应
        }

    private:
        muduo::net::TcpConnectionPtr _conn; // 底层TCP连接对象
        ProtobufCodecPtr _codec;            // Protobuf协议编解码器
        ConsumerManager::ptr _cmp;          // 消费者管理器,用于消息路由
        VirtualHost::ptr _host;             // 虚拟机主机环境
        ThreadPool::ptr _pool;              // 异步工作线程池
        ChannelManager::ptr _channels;      // 信道管理器,管理本连接的所有信道
    };

    // ConnectionManager类:全局连接管理器,负责所有连接的生命周期管理
    class ConnectionManager
    {
    public:
        using ptr = std::shared_ptr<ConnectionManager>; // 智能指针别名

        ConnectionManager() {} // 默认构造函数

        // 创建新连接:当新的TCP连接建立时调用此函数
        void newConnection(const VirtualHost::ptr &host,             // 虚拟机主机环境
                           const ConsumerManager::ptr &cmp,          // 消费者管理器
                           const ProtobufCodecPtr &codec,            // Protobuf协议编解码器
                           const muduo::net::TcpConnectionPtr &conn, // 底层TCP连接
                           const ThreadPool::ptr &pool)              // 工作线程池
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁,保证线程安全

            // 检查连接是否已存在(防止重复添加)
            auto it = _conns.find(conn);
            if (it != _conns.end())
            {
                return; // 连接已存在,直接返回
            }

            // 创建新的Connection对象
            Connection::ptr self_conn = std::make_shared<Connection>(host, cmp, codec, conn, pool);

            // 将新连接添加到连接映射表中
            _conns.insert(std::make_pair(conn, self_conn));
        }

        // 删除连接:当TCP连接断开时调用此函数
        void delConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁,保证线程安全
            _conns.erase(conn);                        // 从连接映射表中删除指定连接
        }

        // 获取连接:根据底层TCP连接对象查找对应的Connection对象
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁,保证线程安全

            auto it = _conns.find(conn); // 查找连接
            if (it == _conns.end())
            {
                return Connection::ptr(); // 连接不存在,返回空指针
            }

            return it->second; // 返回找到的连接对象
        }

    private:
        std::mutex _mutex; // 互斥锁,保护连接映射表的线程安全访问

        // 连接映射表:key为底层TCP连接对象,value为对应的Connection对象
        std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _conns;
    };

} 

五.代码测试

我们所有的测试都是在下面这个test.cpp里面的

cpp 复制代码
#include "../..//mqserver/connection.hpp" 

int main()
{
    // 1. 创建连接管理器实例
    // 使用智能指针管理ConnectionManager生命周期
    mymq::ConnectionManager::ptr cmp = std::make_shared<mymq::ConnectionManager>();
    
    // 2. 创建新连接
    // 向连接管理器注册一个新的网络连接
    cmp->newConnection(
        // 虚拟机主机环境参数
        std::make_shared<mymq::VirtualHost>(
            "host1",                         // 主机名称
            "./data/host1/message/",         // 消息存储目录
            "./data/host1/host1.db"          // 主机数据库文件路径
        ),
        
        // 消费者管理器参数
        std::make_shared<mymq::ConsumerManager>(),
        
        // Protobuf协议编解码器参数(此处使用默认构造)
        mymq::ProtobufCodecPtr(),
        
        // 底层TCP连接对象(此处使用空指针,实际使用时应传入有效的TcpConnectionPtr)
        muduo::net::TcpConnectionPtr(),
        
        // 工作线程池参数(此处使用空指针,实际使用时应传入有效的线程池实例)
        ThreadPool::ptr()
    );
    
    return 0;  // 程序正常退出
}

makefile

cpp 复制代码
test:test.cpp ../../third/include/muduo/protobuf/codec.cc ../../mqcommon/msg.pb.cc ../../mqcommon/proto.pb.cc
	g++ $^ -o $@  -I ../../third/include -L ../../third/lib -lmuduo_net -lmuduo_base -lpthread -lprotobuf -lz -lsqlite3
相关推荐
工程师华哥2 小时前
【网工技术实验】华为S5700交换机堆叠配置实验案例
服务器·网络·华为
不想画图2 小时前
Docker 容器核心配置实战:资源管控、数据卷与容器互联
运维·docker·容器
wheeldown2 小时前
【Linux网络编程】网络基础之MAC地址与IP地址的区别
linux·运维·网络·macos
2501_941982052 小时前
外部群自动化中的“静默心跳”存活检测
运维·自动化
Mr-Wanter2 小时前
搭建局域网时间同步服务器
java·运维·服务器
有谁看见我的剑了?2 小时前
ESXI 虚拟机文件组成学习
运维·学习·云计算
chenyuhao20242 小时前
Linux系统编程:多线程同步与单例模式
linux·服务器·c++·后端·单例模式
代码游侠2 小时前
应用——UDP 网络编程
linux·运维·开发语言·学习·算法
曼巴UE52 小时前
UE C++ FName, FText 测试
服务器·c++·ue5