异步心跳检测机制通常用于检测长连接的对端是否存活,核心逻辑是定时向对端发送心跳包,然后等待对端响应,若多次未收到响应则判定连接失效。本文基于C++11及以上标准,使用标准库提供的线程、定时器和Lambda表达式实现一套简单的异步心跳检测功能,无需依赖第三方库。
核心设计思路
整个机制分为三个核心部分:
- 定时器模块:负责按照设定的间隔触发心跳发送任务,支持启动和停止操作。
- 心跳任务模块:封装心跳包的发送逻辑和对端响应的校验逻辑,使用Lambda表达式作为回调传递给定时器。
- 异步调度模块:使用独立线程运行定时器逻辑,避免阻塞主线程的业务流程。
定时器实现
定时器基于std::thread、std::condition_variable和std::mutex实现,支持设置定时间隔和回调任务。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <chrono>
class SimpleTimer {
private:
std::thread worker_; // 定时器工作线程
std::mutex mtx_; // 互斥锁
std::condition_variable cv_; // 条件变量用于等待
bool stop_flag_; // 停止标志
int interval_ms_; // 定时间隔 单位毫秒
std::function<void()> callback_; // 定时回调任务
public:
// 构造函数 传入定时间隔和回调任务
SimpleTimer(int interval_ms, std::function<void()> callback)
: interval_ms_(interval_ms), callback_(callback), stop_flag_(false) {}
// 启动定时器
void start() {
worker_ = std::thread([this]() {
while (true) {
std::unique_lock<std::mutex> lock(mtx_);
// 等待指定的时间间隔 或者被停止信号唤醒
if (cv_.wait_for(lock, std::chrono::milliseconds(interval_ms_), [this]() {
return stop_flag_;
})) {
// 被停止信号唤醒 退出循环
break;
}
// 执行回调任务
if (callback_) {
callback_();
}
}
});
}
// 停止定时器
void stop() {
{
std::unique_lock<std::mutex> lock(mtx_);
stop_flag_ = true;
}
cv_.notify_one(); // 唤醒等待的线程
if (worker_.joinable()) {
worker_.join();
}
}
// 析构函数 自动停止定时器
~SimpleTimer() {
stop();
}
};
心跳检测模块实现
心跳检测模块维护心跳计数、最大重试次数,使用Lambda表达式作为定时器的回调任务,实现心跳发送和响应校验的逻辑。
#include <atomic>
#include <iostream>
class HeartbeatDetector {
private:
SimpleTimer timer_; // 定时器实例
std::atomic<int> heartbeat_count_;// 已发送未收到响应的心跳计数
int max_retry_; // 最大重试次数 超过则判定连接失效
std::function<void()> send_heartbeat_func_; // 发送心跳包的函数
std::function<void()> on_disconnect_func_; // 连接失效时的回调函数
public:
// 构造函数 传入心跳间隔 最大重试次数 发送心跳函数 断开连接回调
HeartbeatDetector(int interval_ms, int max_retry,
std::function<void()> send_func,
std::function<void()> disconnect_func)
: timer_(interval_ms, [this]() { this->on_timer_tick(); }),
heartbeat_count_(0),
max_retry_(max_retry),
send_heartbeat_func_(send_func),
on_disconnect_func_(disconnect_func) {}
// 启动心跳检测
void start() {
timer_.start();
std::cout << "心跳检测已启动" << std::endl;
}
// 停止心跳检测
void stop() {
timer_.stop();
std::cout << "心跳检测已停止" << std::endl;
}
// 收到对端的心跳响应时调用
void on_heartbeat_response() {
heartbeat_count_ = 0; // 重置计数
std::cout << "收到心跳响应 计数重置" << std::endl;
}
private:
// 定时器触发时的回调逻辑
void on_timer_tick() {
// 发送心跳包
if (send_heartbeat_func_) {
send_heartbeat_func_();
}
heartbeat_count_++;
std::cout << "发送心跳包 当前未响应计数: " << heartbeat_count_.load() << std::endl;
// 检查是否超过最大重试次数
if (heartbeat_count_ > max_retry_) {
std::cout << "超过最大重试次数 连接已失效" << std::endl;
if (on_disconnect_func_) {
on_disconnect_func_();
}
// 停止定时器
timer_.stop();
}
}
};
完整测试示例
下面的示例代码模拟了心跳检测的完整流程,包括模拟发送心跳、模拟收到响应、触发断开连接的逻辑。
#include <iostream>
#include <chrono>
#include <thread>
// 模拟发送心跳包的函数
void mock_send_heartbeat() {
std::cout << "[模拟] 向对端发送心跳包" << std::endl;
}
// 模拟连接断开的回调函数
void mock_on_disconnect() {
std::cout << "[模拟] 连接已断开 执行重连逻辑" << std::endl;
}
int main() {
// 创建心跳检测器 心跳间隔1000毫秒 最大重试3次
HeartbeatDetector detector(1000, 3, mock_send_heartbeat, mock_on_disconnect);
detector.start();
// 模拟前2次心跳正常收到响应
std::this_thread::sleep_for(std::chrono::milliseconds(2200));
detector.on_heartbeat_response(); // 第2次心跳后收到响应
// 模拟后续不再收到响应 直到触发断开
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
// 手动停止检测(实际场景中可能不需要手动调用 断开时会自动停止)
detector.stop();
return 0;
}
注意事项
- 实际开发中,发送心跳包的逻辑需要替换为真实的网络发送代码,比如使用socket发送自定义协议的心跳包。
- 响应校验逻辑需要根据实际协议调整,比如校验心跳包的序列号是否匹配。
- 如果需要在多线程环境下操作
HeartbeatDetector的实例,需要额外添加线程安全保护。 - 定时器的间隔和最大重试次数可以根据实际网络环境调整,避免误判连接失效。