在一个RPC框架或网络库中,Connection 类代表了一个客户端与服务器之间的单个连接,并且负责管理该连接上的所有通信活动。
成员变量
tcp::socket socket_;
#ifdef CINATRA_ENABLE_SSL
std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket &>> ssl_stream_ =
nullptr;
#endif
bool has_shake_ = false;
char head_[HEAD_LEN];
std::vector<char> body_;
std::uint64_t req_id_;
request_type req_type_;
rpc_header header_;
uint32_t write_size_ = 0;
asio::steady_timer timer_;
std::size_t timeout_seconds_;
int64_t conn_id_ = 0;
bool has_closed_;
std::deque<message_type> write_queue_;
std::function<void(std::string, std::string, std::weak_ptr<connection>)>
callback_;
std::function<void(std::shared_ptr<connection>, std::string)> *on_net_err_ =
nullptr;
router &router_;
nonstd::any user_data_;
bool delay_ = false; 成员变量
1. 网络通信核心变量
tcp::socket socket_
-
类型:
asio::ip::tcp::socket -
作用: 基础TCP套接字,处理所有网络IO操作
-
特点:
-
绑定到io_service执行上下文
-
生命周期与connection对象一致
-
提供异步读写接口
-
SSL相关变量
#ifdef CINATRA_ENABLE_SSL std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket &>> ssl_stream_ = nullptr; #endif bool has_shake_ = false;
-
ssl_stream_:
-
类型: SSL流对象的智能指针
-
作用: 包装普通socket提供SSL/TLS加密通信
-
特点: 条件编译,仅在开启SSL时存在
-
-
has_shake_:
-
类型: bool
-
作用: 标记SSL握手是否完成
-
特点: 避免重复握手
-
2. 数据缓冲区
char head_[HEAD_LEN]
-
类型: 固定大小字符数组
-
作用: 存储协议头数据
-
特点:
-
大小由HEAD_LEN定义(通常8-16字节)
-
包含魔数、请求类型、body长度等元数据
-
零拷贝解析提高效率
-
std::vector<char> body_
-
类型: 动态字符向量
-
作用: 存储消息体数据
-
特点:
-
初始大小INIT_BUF_SIZE(如1KB)
-
按需扩容(不超过MAX_BUF_LEN)
-
复用缓冲区减少内存分配
-
3. 协议处理变量
rpc_header header_
-
类型: 协议头结构体
-
作用: 解析后的协议头信息
-
典型结构:
struct rpc_header { uint32_t magic; // 魔数标识 request_type type; // 请求类型 uint32_t body_len; // 消息体长度 uint64_t req_id; // 请求ID };
std::uint64_t req_id_
-
作用: 当前处理的请求ID
-
特点: 用于请求-响应匹配
request_type req_type_
-
作用: 标识当前请求类型(req_res/sub_pub)
-
枚举值:
enum class request_type { req_res = 0, // 请求-响应模式 sub_pub = 1 // 发布-订阅模式 };
4. 写操作相关变量
uint32_t write_size_
-
作用: 当前正在写入的消息大小
-
特点: 确保完整写入大数据包
std::deque<message_type> write_queue_
-
message_type定义:
struct message_type { uint64_t req_id; request_type req_type; std::shared_ptr<std::string> content; }; -
作用: 写消息队列
-
特点:
-
保证消息顺序发送
-
共享指针管理消息内存
-
实现写操作流水线
-
5. 连接控制变量
asio::steady_timer timer_
-
作用: 超时控制定时器
-
特点:
-
用于检测空闲连接
-
可配置超时时间(timeout_seconds_)
-
自动取消机制
-
std::size_t timeout_seconds_
-
作用: 连接超时时间(秒)
-
特殊值: 0表示不启用超时
bool has_closed_
-
作用: 连接状态标记
-
特点: 原子操作保证线程安全
int64_t conn_id_
-
作用: 连接唯一标识符
-
用途: 会话管理/日志追踪
6. 回调与路由
router &router_
-
作用: 请求路由处理器
-
功能:
-
维护函数注册表
-
分发RPC调用
-
处理序列化/反序列化
-
回调函数
std::function<void(std::string, std::string, std::weak_ptr<connection>)> callback_; std::function<void(std::shared_ptr<connection>, std::string)> *on_net_err_ = nullptr;
-
callback_:
-
类型: 主题+消息+连接弱引用的回调
-
作用: 处理订阅发布消息
-
-
on_net_err_:
-
类型: 网络错误回调指针
-
作用: 通知外部网络异常
-
特点: 使用指针避免空回调开销
-
7. 扩展功能变量
nonstd::any user_data_
-
作用: 用户自定义数据容器
-
特点:
-
类型安全的数据存储
-
可用于附加会话信息
-
替代void*的更安全方案
-
bool delay_
-
作用: 响应延迟标记
-
用途:
-
控制是否立即发送响应
-
支持异步处理模式
-
成员函数解析
1. 连接生命周期管理
start() - 启动连接处理
void start() {
if (is_ssl() && !has_shake_) {
async_handshake(); // SSL连接需要先握手
} else {
read_head(); // 直接开始读取数据
}
}
-
功能:启动连接的消息处理循环
-
逻辑分支:
-
SSL连接且未握手 → 执行SSL握手
-
普通连接或已握手 → 直接读取数据
-
-
特点:作为连接处理的统一入口
has_closed() - 连接状态检查
bool has_closed() const { return has_closed_; }
-
作用:提供线程安全的连接状态查询
-
使用场景:在需要检查连接是否活跃时调用
2. 响应处理函数
response() - 发送响应
void response(uint64_t req_id, std::string data, request_type req_type = request_type::req_res) {
assert(data.size() < MAX_BUF_LEN);
auto sp_data = std::make_shared<std::string>(std::move(data));
asio::post(socket_.get_executor(), [this, weak = weak_from_this(), sp_data, req_id, req_type] {
if (auto conn = weak.lock()) {
response_internal(req_id, std::move(sp_data), req_type);
}
});
}
-
参数:
-
req_id:请求ID用于匹配 -
data:响应数据(移动语义) -
req_type:请求类型(默认请求-响应模式)
-
-
关键设计:
-
使用shared_ptr管理数据生命周期
-
通过weak_ptr安全访问connection对象
-
在socket的执行器中序列化写操作
-
pack_and_response() - 打包并响应模板函数
template <typename T>
void pack_and_response(uint64_t req_id, T data) {
auto result = msgpack_codec::pack_args_str(result_code::OK, std::move(data));
response(req_id, std::move(result));
}
-
功能:将数据打包为msgpack格式后发送
-
特点:
-
自动添加成功结果码(result_code::OK)
-
支持任意可序列化类型
-
简化响应发送流程
-
3. 连接属性管理
连接标识管理
void set_conn_id(int64_t id) { conn_id_ = id; }
int64_t conn_id() const { return conn_id_; }
-
作用:设置/获取连接唯一标识
-
用途:用于会话管理和日志追踪
用户数据存储
template <typename T>
void set_user_data(const T &data) { user_data_ = data; }
template <typename T>
T get_user_data() {
return nonstd::any_cast<T>(user_data_);
}
-
实现:基于type-erasure的任意数据存储
-
特点:
-
类型安全的存取接口
-
可用于附加业务上下文
-
替代void*的更安全方案
-
4. 网络信息获取
remote_address() - 获取客户端地址
std::string remote_address() const {
if (has_closed_) return "";
asio::error_code ec;
auto endpoint = socket_.remote_endpoint(ec);
return ec ? "" : endpoint.address().to_string();
}
-
功能:获取对端IP地址字符串
-
错误处理:
-
连接已关闭返回空字符串
-
获取失败返回空字符串
-
-
线程安全:无锁实现,适合并发调用
5. 发布订阅功能
publish() - 发布消息
void publish(const std::string &key, const std::string &data) {
auto result = msgpack_codec::pack_args_str(result_code::OK, key, data);
response(0, std::move(result), request_type::sub_pub);
}
-
特点:
-
使用0作为特殊请求ID
-
指定sub_pub请求类型
-
自动打包主题和数据
-
set_callback() - 设置订阅回调
void set_callback(std::function<void(std::string, std::string,
std::weak_ptr<connection>)> callback) {
callback_ = std::move(callback);
}
-
回调参数:
-
主题名称
-
消息内容
-
连接弱引用(避免循环引用)
-
6. SSL/TLS配置
init_ssl_context() - 初始化SSL上下文
void init_ssl_context(const ssl_configure &ssl_conf) {
asio::ssl::context ssl_context(asio::ssl::context::sslv23);
ssl_context.set_options(ssl_options);
ssl_context.use_certificate_chain_file(ssl_conf.cert_file);
ssl_context.use_private_key_file(ssl_conf.key_file, asio::ssl::context::pem);
ssl_stream_ = std::make_unique<asio::ssl::stream<asio::ip::tcp::socket&>>(socket_, ssl_context);
}
-
安全配置:
-
禁用不安全的SSLv2
-
单次DH密钥交换
-
加载证书和私钥文件
-
-
错误处理:捕获异常并打印日志
7. 其他控制功能
set_delay() - 延迟响应控制
void set_delay(bool delay) { delay_ = delay; }
-
用途:标记是否需要延迟发送响应
-
场景:用于异步处理完成后手动发送响应
on_network_error() - 设置网络错误回调
void on_network_error(std::function<void(std::shared_ptr<connection>,
std::string)> &on_net_err) {
on_net_err_ = &on_net_err;
}
-
设计特点:
-
使用指针存储回调(避免空回调对象开销)
-
参数包含连接对象和错误信息
-
在超时、协议错误等情况下触发
-
私有成员函数解析
1. 核心消息处理流程
读操作流程
read_head() - 读取消息头
void read_head() {
reset_timer(); // 重置超时定时器
async_read_head([this, self](asio::error_code ec, std::size_t length) {
// 协议头处理逻辑
rpc_header* header = (rpc_header*)(head_);
if (header->magic != MAGIC_NUM) {
close(); // 协议错误立即关闭连接
return;
}
// 解析并验证消息体长度
if (body_len > 0 && body_len < MAX_BUF_LEN) {
read_body(header->func_id, body_len); // 继续读取消息体
}
else if (body_len == 0) {
read_head(); // 心跳包,继续读下一个消息头
}
});
}
-
关键点:
-
每次读取前重置超时定时器
-
严格验证协议魔数和消息长度
-
支持心跳包(body_len=0)的特殊处理
-
read_body() - 读取消息体
void read_body(uint32_t func_id, std::size_t size) {
async_read(size, [this, func_id, self](asio::error_code ec, std::size_t length) {
cancel_timer(); // 取消当前超时检测
if (req_type_ == request_type::req_res) {
// RPC调用路由处理
auto ret = router_.route(func_id, {body_.data(), length}, ...);
response_internal(req_id_, std::move(ret.result));
}
else if (req_type_ == request_type::sub_pub) {
// 发布订阅消息回调
callback_(topic, message, this->shared_from_this());
}
read_head(); // 继续读下一个消息
});
}
-
关键点:
-
根据请求类型分流处理
-
自动续读实现持续通信
-
消息体缓冲区复用
-
写操作流程
response_internal() - 响应处理
void response_internal(uint64_t req_id, std::shared_ptr<std::string> data) {
write_queue_.emplace_back(message_type{req_id, req_type, std::move(data)});
if (write_queue_.size() == 1) {
write(); // 立即发送如果是队列中唯一消息
}
}
-
设计特点:
-
写操作队列化保证顺序
-
共享指针管理消息内存
-
触发式发送机制
-
write() - 实际写入操作
void write() {
std::array<asio::const_buffer, 2> write_buffers = {
asio::buffer(&header_, sizeof(rpc_header)),
asio::buffer(msg.content->data(), write_size_)
};
async_write(write_buffers, [this, self](asio::error_code ec, std::size_t length) {
write_queue_.pop_front();
if (!write_queue_.empty()) write(); // 继续发送队列中下一条
});
}
-
优化点:
-
复合缓冲区减少系统调用
-
自动连续发送机制
-
零拷贝数据传递
-
2. SSL/TLS 安全通信
async_handshake() - SSL握手
void async_handshake() {
ssl_stream_->async_handshake(asio::ssl::stream_base::server,
[this, self](const asio::error_code& error) {
if (!error) {
has_shake_ = true;
read_head(); // 握手成功后开始正常通信
}
});
}
-
安全特性:
-
服务端模式握手
-
状态标记保证只握手一次
-
错误时立即关闭连接
-
3. 连接生命周期管理
close() - 连接关闭
void close(bool close_ssl = true) {
#ifdef CINATRA_ENABLE_SSL
if (close_ssl && ssl_stream_) {
ssl_stream_->shutdown(ec); // 优雅关闭SSL
}
#endif
socket_.shutdown(tcp::socket::shutdown_both);
socket_.close();
has_closed_ = true;
}
-
资源管理:
-
区分SSL和普通关闭
-
双重关闭保证资源释放
-
状态标记避免重复关闭
-
超时控制
reset_timer() - 重置定时器
void reset_timer() {
timer_.expires_from_now(std::chrono::seconds(timeout_seconds_));
timer_.async_wait([this, self](const asio::error_code& ec) {
if (!ec) close(false); // 超时触发连接关闭
});
}
cancel_timer() - 取消定时器
void cancel_timer() {
timer_.cancel(); // 正常响应时取消超时检测
}
-
设计亮点:
-
精确到秒的超时控制
-
异步等待不阻塞线程
-
自动续期机制
-
4. 异步IO模板方法
通用异步IO封装
template <typename Handler>
void async_read_head(Handler handler) {
if (is_ssl()) {
asio::async_read(*ssl_stream_, asio::buffer(head_), handler);
} else {
asio::async_read(socket_, asio::buffer(head_), handler);
}
}
-
模板特性:
-
统一SSL和非SSL接口
-
完美转发handler
-
编译期多态
-
5. 调试支持
日志输出
template <typename... Args>
void print(Args... args) {
#ifdef _DEBUG
(std::cout << ... << args) << "\n"; // C++17折叠表达式
#endif
}
-
调试功能:
-
条件编译的调试输出
-
支持多参数打印
-
专用于错误和异常
-

1416

被折叠的 条评论
为什么被折叠?



