目录
[一.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():注册新建立的连接
- 检查连接是否已存在(防止重复注册)
- 创建Connection对象并建立完整资源链
- 将连接加入全局管理映射表
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
