C++网络编程心跳机制与连接保活:长连接稳定性保障

C++网络编程心跳机制与连接保活:长连接稳定性保障

创建日期 : 2026-03-25
更新日期 : 2026-03-25
作者 : zry
标签: C++, 网络编程, 心跳机制, 连接保活, TCP, 超时检测


📋 目录

  1. 引言
  2. 为什么需要心跳机制
  3. 心跳机制原理
  4. TCP层保活
  5. 应用层心跳
  6. 心跳策略设计
  7. 核心代码实现
  8. 断线重连机制
  9. 生产环境最佳实践
  10. 总结

引言

在长连接网络应用中(如物联网设备连接、实时消息推送),连接的稳定性至关重要。心跳机制(Heartbeat) 是检测连接活性、及时发现网络故障的关键技术。

本文基于AIDC自动气象站数据收集系统的实践,深入讲解C++网络编程中的心跳机制设计与实现。


为什么需要心跳机制

连接断开场景

连接断开场景
网络故障
网线拔出
WiFi断连
路由器重启
设备故障
设备断电
程序崩溃
系统重启
中间件问题
NAT超时
防火墙断开
负载均衡器清理

TCP的半连接问题

服务端 网络 客户端 服务端 网络 客户端 网络故障(网线拔出) 客户端认为连接正常 服务端认为连接正常 超时后才知断开 建立连接 确认 发送数据(阻塞)

问题: TCP协议本身无法快速检测到物理层故障,需要应用层心跳机制辅助。


心跳机制原理

心跳机制全景

心跳机制




心跳发送
收到响应?
连接正常
重试
超过阈值?
判定断开
触发重连

心跳模式对比

模式 机制 优点 缺点 适用场景
TCP Keepalive 协议层保活 无应用代码 不够及时 简单应用
应用层心跳 自定义心跳包 灵活可控 需要实现 生产环境
双向心跳 双方互发 检测更及时 复杂度高 高可靠需求

TCP层保活

TCP Keepalive配置

cpp 复制代码
/**
 * @brief TCP Keepalive配置
 */
class TcpKeepaliveConfig {
public:
    /**
     * @brief 启用TCP Keepalive(Linux)
     * @param socket_fd 套接字描述符
     * @param idle_sec 空闲多久开始探测
     * @param interval_sec 探测间隔
     * @param count 探测次数
     */
    static bool Enable(int socket_fd, 
                       int idle_sec = 60,
                       int interval_sec = 10, 
                       int count = 3) {
        int enable = 1;
        
        // 启用keepalive
        if (setsockopt(socket_fd, SOL_SOCKET, SO_KEEPALIVE, 
                      &enable, sizeof(enable)) < 0) {
            ZRY_LOG_ERROR("启用SO_KEEPALIVE失败: {}", strerror(errno));
            return false;
        }
        
#ifdef __linux__
        // TCP_KEEPIDLE: 空闲多久开始探测
        if (setsockopt(socket_fd, IPPROTO_TCP, TCP_KEEPIDLE,
                      &idle_sec, sizeof(idle_sec)) < 0) {
            ZRY_LOG_ERROR("设置TCP_KEEPIDLE失败: {}", strerror(errno));
            return false;
        }
        
        // TCP_KEEPINTVL: 探测间隔
        if (setsockopt(socket_fd, IPPROTO_TCP, TCP_KEEPINTVL,
                      &interval_sec, sizeof(interval_sec)) < 0) {
            ZRY_LOG_ERROR("设置TCP_KEEPINTVL失败: {}", strerror(errno));
            return false;
        }
        
        // TCP_KEEPCNT: 探测次数
        if (setsockopt(socket_fd, IPPROTO_TCP, TCP_KEEPCNT,
                      &count, sizeof(count)) < 0) {
            ZRY_LOG_ERROR("设置TCP_KEEPCNT失败: {}", strerror(errno));
            return false;
        }
#endif
        
        ZRY_LOG_INFO("TCP Keepalive已启用: idle={}, interval={}, count={}",
                    idle_sec, interval_sec, count);
        return true;
    }
};

TCP保活限制

cpp 复制代码
/**
 * @brief TCP Keepalive的局限性说明
 * 
 * 1. 无法区分网络故障和对端崩溃
 * 2. 探测间隔受操作系统限制
 * 3. 不适用于需要快速检测的场景
 * 4. 某些中间件可能过滤keepalive包
 * 
 * 因此生产环境推荐使用应用层心跳
 */

应用层心跳

心跳协议设计

心跳协议帧
Header
Type: 1字节
Length: 2字节
Timestamp: 8字节
Sequence: 4字节
Payload: 可变
CRC: 4字节
0x01: Heartbeat Req
0x02: Heartbeat Ack

心跳消息定义

cpp 复制代码
/**
 * @file heartbeat_protocol.hpp
 * @brief 心跳协议定义
 */

#ifndef ZRY_HEARTBEAT_PROTOCOL_HPP
#define ZRY_HEARTBEAT_PROTOCOL_HPP

#include <cstdint>
#include <chrono>

namespace zry::net {

/**
 * @brief 心跳消息类型
 */
enum class HeartbeatType : uint8_t {
    REQUEST = 0x01,   // 心跳请求
    RESPONSE = 0x02   // 心跳响应
};

/**
 * @brief 心跳消息
 */
struct HeartbeatMessage {
    static constexpr uint8_t MAGIC_HEADER = 0xAA;
    static constexpr uint8_t VERSION = 0x01;
    
    uint8_t magic;        // 魔数
    uint8_t version;      // 协议版本
    uint8_t type;         // 消息类型
    uint16_t length;      // 消息长度
    uint32_t sequence;    // 序列号
    uint64_t timestamp;   // 发送时间戳(微秒)
    uint32_t crc32;       // CRC校验
    
    /**
     * @brief 创建心跳请求
     */
    static HeartbeatMessage CreateRequest(uint32_t seq) {
        HeartbeatMessage msg{};
        msg.magic = MAGIC_HEADER;
        msg.version = VERSION;
        msg.type = static_cast<uint8_t>(HeartbeatType::REQUEST);
        msg.length = sizeof(HeartbeatMessage);
        msg.sequence = seq;
        msg.timestamp = NowUs();
        msg.crc32 = CalculateCRC32(msg);
        return msg;
    }
    
    /**
     * @brief 创建心跳响应
     */
    static HeartbeatMessage CreateResponse(uint32_t seq) {
        HeartbeatMessage msg{};
        msg.magic = MAGIC_HEADER;
        msg.version = VERSION;
        msg.type = static_cast<uint8_t>(HeartbeatType::RESPONSE);
        msg.length = sizeof(HeartbeatMessage);
        msg.sequence = seq;
        msg.timestamp = NowUs();
        msg.crc32 = CalculateCRC32(msg);
        return msg;
    }
    
    /**
     * @brief 验证消息有效性
     */
    bool IsValid() const {
        return magic == MAGIC_HEADER &&
               version == VERSION &&
               crc32 == CalculateCRC32(*this);
    }
    
    /**
     * @brief 计算往返延迟(RTT)
     */
    int64_t CalculateRTT() const {
        return NowUs() - timestamp;
    }

private:
    static uint64_t NowUs() {
        using namespace std::chrono;
        return duration_cast<microseconds>(
            system_clock::now().time_since_epoch()).count();
    }
    
    static uint32_t CalculateCRC32(const HeartbeatMessage& msg) {
        // 简化的CRC32计算
        // 实际使用zlib等库
        return 0;  // 占位
    }
};

} // namespace zry::net

#endif // ZRY_HEARTBEAT_PROTOCOL_HPP

心跳策略设计

自适应心跳

网络正常
降低心跳频率
网络不稳定
增加心跳频率
移动网络
保守频率
有线网络
激进频率

cpp 复制代码
/**
 * @brief 自适应心跳策略
 */
class AdaptiveHeartbeatStrategy {
public:
    struct Config {
        int min_interval_ms = 5000;    // 最小间隔
        int max_interval_ms = 60000;   // 最大间隔
        int initial_interval_ms = 10000;  // 初始间隔
        int rtt_threshold_ms = 500;    // RTT阈值
    };
    
    explicit AdaptiveHeartbeatStrategy(const Config& config)
        : config_(config), current_interval_(config.initial_interval_ms) {}
    
    /**
     * @brief 根据RTT调整心跳间隔
     */
    void AdjustBasedOnRTT(int64_t rtt_ms) {
        if (rtt_ms > config_.rtt_threshold_ms * 2) {
            // RTT过高,缩短心跳间隔
            current_interval_ = std::max(
                current_interval_ / 2,
                config_.min_interval_ms
            );
            consecutive_good_ = 0;
            consecutive_bad_++;
            
        } else if (rtt_ms < config_.rtt_threshold_ms) {
            // RTT良好,可考虑延长间隔
            consecutive_good_++;
            consecutive_bad_ = 0;
            
            if (consecutive_good_ >= 3) {
                current_interval_ = std::min(
                    current_interval_ * 2,
                    config_.max_interval_ms
                );
                consecutive_good_ = 0;
            }
        }
    }
    
    int GetCurrentIntervalMs() const {
        return current_interval_;
    }
    
    bool IsNetworkStable() const {
        return consecutive_bad_ < 3;
    }

private:
    Config config_;
    int current_interval_;
    int consecutive_good_ = 0;
    int consecutive_bad_ = 0;
};

核心代码实现

心跳管理器

cpp 复制代码
/**
 * @file heartbeat_manager.hpp
 * @brief 心跳管理器
 */

#ifndef ZRY_HEARTBEAT_MANAGER_HPP
#define ZRY_HEARTBEAT_MANAGER_HPP

#include "heartbeat_protocol.hpp"
#include <functional>
#include <atomic>
#include <thread>
#include <mutex>

namespace zry::net {

/**
 * @brief 心跳回调接口
 */
class HeartbeatCallbacks {
public:
    virtual ~HeartbeatCallbacks() = default;
    virtual void OnHeartbeatSent() = 0;
    virtual void OnHeartbeatReceived(int64_t rtt_ms) = 0;
    virtual void OnHeartbeatTimeout() = 0;
    virtual void OnConnectionLost() = 0;
};

/**
 * @brief 心跳管理器
 */
class HeartbeatManager {
public:
    struct Config {
        int heartbeat_interval_ms = 10000;   // 心跳间隔
        int heartbeat_timeout_ms = 30000;    // 超时时间
        int max_missed_heartbeats = 3;        // 最大丢失次数
    };
    
    HeartbeatManager(Config config, 
                     std::function<bool(const void*, size_t)> sender)
        : config_(config),
          sender_(sender),
          running_(false),
          next_sequence_(1),
          missed_heartbeats_(0) {}
    
    ~HeartbeatManager() {
        Stop();
    }
    
    /**
     * @brief 启动心跳
     */
    void Start() {
        if (running_) return;
        
        running_ = true;
        missed_heartbeats_ = 0;
        
        // 启动发送线程
        sender_thread_ = std::thread(&HeartbeatManager::SendLoop, this);
        
        // 启动检测线程
        checker_thread_ = std::thread(&HeartbeatManager::CheckLoop, this);
        
        ZRY_LOG_INFO("心跳管理器已启动,间隔: {}ms", config_.heartbeat_interval_ms);
    }
    
    /**
     * @brief 停止心跳
     */
    void Stop() {
        if (!running_) return;
        
        running_ = false;
        cv_.notify_all();
        
        if (sender_thread_.joinable()) {
            sender_thread_.join();
        }
        if (checker_thread_.joinable()) {
            checker_thread_.join();
        }
        
        ZRY_LOG_INFO("心跳管理器已停止");
    }
    
    /**
     * @brief 处理收到的心跳响应
     */
    void OnHeartbeatResponse(const HeartbeatMessage& msg) {
        if (!msg.IsValid()) {
            ZRY_LOG_WARN("收到无效的心跳响应");
            return;
        }
        
        std::lock_guard<std::mutex> lock(mutex_);
        
        if (msg.sequence == pending_sequence_) {
            int64_t rtt = msg.CalculateRTT() / 1000;  // 转换为毫秒
            last_rtt_ms_ = rtt;
            missed_heartbeats_ = 0;
            response_received_ = true;
            
            if (callbacks_) {
                callbacks_->OnHeartbeatReceived(rtt);
            }
            
            ZRY_LOG_DEBUG("心跳响应收到,RTT: {}ms", rtt);
        }
    }
    
    /**
     * @brief 处理收到的心跳请求
     */
    void OnHeartbeatRequest(const HeartbeatMessage& msg) {
        if (!msg.IsValid()) return;
        
        // 立即回复
        auto response = HeartbeatMessage::CreateResponse(msg.sequence);
        sender_(&response, sizeof(response));
        
        ZRY_LOG_DEBUG("回复心跳请求,seq: {}", msg.sequence);
    }
    
    void SetCallbacks(HeartbeatCallbacks* callbacks) {
        callbacks_ = callbacks;
    }
    
    int64_t GetLastRTT() const {
        return last_rtt_ms_;
    }

private:
    void SendLoop() {
        while (running_) {
            {
                std::unique_lock<std::mutex> lock(mutex_);
                
                uint32_t seq = next_sequence_++;
                pending_sequence_ = seq;
                response_received_ = false;
                
                // 发送心跳
                auto request = HeartbeatMessage::CreateRequest(seq);
                if (sender_(&request, sizeof(request))) {
                    missed_heartbeats_++;
                    
                    if (callbacks_) {
                        callbacks_->OnHeartbeatSent();
                    }
                    
                    ZRY_LOG_DEBUG("发送心跳,seq: {}", seq);
                }
            }
            
            // 等待下一次心跳
            std::unique_lock<std::mutex> lock(mutex_);
            cv_.wait_for(lock, 
                        std::chrono::milliseconds(config_.heartbeat_interval_ms),
                        [this] { return !running_; });
        }
    }
    
    void CheckLoop() {
        while (running_) {
            std::this_thread::sleep_for(
                std::chrono::milliseconds(config_.heartbeat_timeout_ms)
            );
            
            if (!running_) break;
            
            std::lock_guard<std::mutex> lock(mutex_);
            
            if (!response_received_ && missed_heartbeats_ > 0) {
                ZRY_LOG_WARN("心跳超时,连续丢失: {}/{}",
                           missed_heartbeats_, config_.max_missed_heartbeats);
                
                if (callbacks_) {
                    callbacks_->OnHeartbeatTimeout();
                }
                
                if (missed_heartbeats_ >= config_.max_missed_heartbeats) {
                    ZRY_LOG_ERROR("心跳连续丢失超过阈值,判定连接断开");
                    
                    if (callbacks_) {
                        callbacks_->OnConnectionLost();
                    }
                    
                    // 停止心跳
                    running_ = false;
                }
            }
        }
    }

private:
    Config config_;
    std::function<bool(const void*, size_t)> sender_;
    HeartbeatCallbacks* callbacks_ = nullptr;
    
    std::atomic<bool> running_;
    std::thread sender_thread_;
    std::thread checker_thread_;
    
    std::mutex mutex_;
    std::condition_variable cv_;
    
    uint32_t next_sequence_;
    uint32_t pending_sequence_;
    bool response_received_ = false;
    int missed_heartbeats_;
    int64_t last_rtt_ms_ = -1;
};

} // namespace zry::net

#endif // ZRY_HEARTBEAT_MANAGER_HPP

连接保活管理器

cpp 复制代码
/**
 * @file connection_keepalive.hpp
 * @brief 连接保活管理器
 */

#ifndef ZRY_CONNECTION_KEEPALIVE_HPP
#define ZRY_CONNECTION_KEEPALIVE_HPP

#include "heartbeat_manager.hpp"
#include <memory>

namespace zry::net {

/**
 * @brief 连接保活管理器
 * 
 * 结合TCP keepalive和应用层心跳
 */
class ConnectionKeepalive {
public:
    struct Config {
        // TCP keepalive配置
        bool enable_tcp_keepalive = true;
        int tcp_keepalive_idle_sec = 60;
        int tcp_keepalive_interval_sec = 10;
        int tcp_keepalive_count = 3;
        
        // 应用层心跳配置
        bool enable_app_heartbeat = true;
        int heartbeat_interval_ms = 10000;
        int heartbeat_timeout_ms = 30000;
    };
    
    ConnectionKeepalive(int socket_fd, const Config& config)
        : socket_fd_(socket_fd), config_(config) {}
    
    /**
     * @brief 启用保活
     */
    bool Enable() {
        // 1. 启用TCP keepalive
        if (config_.enable_tcp_keepalive) {
            if (!TcpKeepaliveConfig::Enable(socket_fd_,
                                             config_.tcp_keepalive_idle_sec,
                                             config_.tcp_keepalive_interval_sec,
                                             config_.tcp_keepalive_count)) {
                return false;
            }
        }
        
        // 2. 启动应用层心跳
        if (config_.enable_app_heartbeat) {
            HeartbeatManager::Config hb_config;
            hb_config.heartbeat_interval_ms = config_.heartbeat_interval_ms;
            hb_config.heartbeat_timeout_ms = config_.heartbeat_timeout_ms;
            
            heartbeat_manager_ = std::make_unique<HeartbeatManager>(
                hb_config,
                [this](const void* data, size_t len) {
                    return SendData(data, len);
                }
            );
            
            heartbeat_manager_->Start();
        }
        
        return true;
    }
    
    void Disable() {
        if (heartbeat_manager_) {
            heartbeat_manager_->Stop();
        }
    }
    
    void OnDataReceived(const void* data, size_t len) {
        if (!heartbeat_manager_) return;
        
        if (len >= sizeof(HeartbeatMessage)) {
            auto* msg = static_cast<const HeartbeatMessage*>(data);
            
            if (msg->magic == HeartbeatMessage::MAGIC_HEADER) {
                if (msg->type == static_cast<uint8_t>(HeartbeatType::REQUEST)) {
                    heartbeat_manager_->OnHeartbeatRequest(*msg);
                } else if (msg->type == static_cast<uint8_t>(HeartbeatType::RESPONSE)) {
                    heartbeat_manager_->OnHeartbeatResponse(*msg);
                }
            }
        }
    }
    
    void SetCallbacks(HeartbeatCallbacks* callbacks) {
        if (heartbeat_manager_) {
            heartbeat_manager_->SetCallbacks(callbacks);
        }
    }
    
    int64_t GetLastRTT() const {
        if (heartbeat_manager_) {
            return heartbeat_manager_->GetLastRTT();
        }
        return -1;
    }

private:
    bool SendData(const void* data, size_t len) {
        ssize_t sent = send(socket_fd_, data, len, MSG_NOSIGNAL);
        return sent == static_cast<ssize_t>(len);
    }

private:
    int socket_fd_;
    Config config_;
    std::unique_ptr<HeartbeatManager> heartbeat_manager_;
};

} // namespace zry::net

#endif // ZRY_CONNECTION_KEEPALIVE_HPP

断线重连机制

指数退避重连

cpp 复制代码
/**
 * @brief 指数退避重连策略
 */
class ReconnectStrategy {
public:
    struct Config {
        int initial_delay_ms = 1000;      // 初始延迟
        int max_delay_ms = 60000;          // 最大延迟
        int backoff_multiplier = 2;        // 退避乘数
        int max_attempts = 0;              // 最大尝试次数(0表示无限)
    };
    
    explicit ReconnectStrategy(const Config& config)
        : config_(config), 
          current_delay_(config.initial_delay_ms),
          attempt_count_(0) {}
    
    /**
     * @brief 获取下次重连延迟
     */
    int GetNextDelayMs() {
        attempt_count_++;
        
        if (config_.max_attempts > 0 && attempt_count_ > config_.max_attempts) {
            return -1;  // 超过最大尝试次数
        }
        
        int delay = current_delay_;
        
        // 计算下次延迟
        current_delay_ = std::min(
            current_delay_ * config_.backoff_multiplier,
            config_.max_delay_ms
        );
        
        // 添加随机抖动(避免惊群)
        delay += rand() % (delay / 10);
        
        return delay;
    }
    
    void Reset() {
        current_delay_ = config_.initial_delay_ms;
        attempt_count_ = 0;
    }
    
    int GetAttemptCount() const {
        return attempt_count_;
    }

private:
    Config config_;
    int current_delay_;
    int attempt_count_;
};

自动重连客户端

cpp 复制代码
/**
 * @brief 自动重连TCP客户端
 */
class AutoReconnectClient : public HeartbeatCallbacks {
public:
    AutoReconnectClient(const std::string& host, int port)
        : host_(host), port_(port), connected_(false), should_stop_(false) {}
    
    void Start() {
        should_stop_ = false;
        reconnect_strategy_.Reset();
        
        connect_thread_ = std::thread(&AutoReconnectClient::ConnectLoop, this);
    }
    
    void Stop() {
        should_stop_ = true;
        Disconnect();
        
        if (connect_thread_.joinable()) {
            connect_thread_.join();
        }
    }
    
    // HeartbeatCallbacks实现
    void OnHeartbeatSent() override {
        ZRY_LOG_DEBUG("心跳已发送");
    }
    
    void OnHeartbeatReceived(int64_t rtt_ms) override {
        ZRY_LOG_DEBUG("心跳响应,RTT: {}ms", rtt_ms);
        reconnect_strategy_.Reset();  // 收到心跳,重置重连策略
    }
    
    void OnHeartbeatTimeout() override {
        ZRY_LOG_WARN("心跳超时");
    }
    
    void OnConnectionLost() override {
        ZRY_LOG_ERROR("连接丢失,准备重连");
        Disconnect();
    }

private:
    void ConnectLoop() {
        while (!should_stop_) {
            if (!connected_) {
                if (TryConnect()) {
                    connected_ = true;
                    reconnect_strategy_.Reset();
                    OnConnected();
                } else {
                    int delay = reconnect_strategy_.GetNextDelayMs();
                    if (delay < 0) {
                        ZRY_LOG_ERROR("重连次数超过限制,放弃");
                        break;
                    }
                    
                    ZRY_LOG_INFO("{}ms后尝试第{}次重连...", 
                               delay, reconnect_strategy_.GetAttemptCount());
                    std::this_thread::sleep_for(std::chrono::milliseconds(delay));
                }
            } else {
                // 连接正常,检查连接状态
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        }
    }
    
    bool TryConnect() {
        // 创建套接字
        socket_fd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (socket_fd_ < 0) {
            return false;
        }
        
        // 设置非阻塞(用于超时连接)
        // ...
        
        // 连接
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port_);
        inet_pton(AF_INET, host_.c_str(), &addr.sin_addr);
        
        int result = connect(socket_fd_, (struct sockaddr*)&addr, sizeof(addr));
        if (result < 0 && errno != EINPROGRESS) {
            close(socket_fd_);
            return false;
        }
        
        // 启用保活
        ConnectionKeepalive::Config ka_config;
        keepalive_ = std::make_unique<ConnectionKeepalive>(socket_fd_, ka_config);
        keepalive_->SetCallbacks(this);
        
        if (!keepalive_->Enable()) {
            close(socket_fd_);
            return false;
        }
        
        ZRY_LOG_INFO("连接到 {}:{} 成功", host_, port_);
        return true;
    }
    
    void Disconnect() {
        if (keepalive_) {
            keepalive_->Disable();
            keepalive_.reset();
        }
        
        if (socket_fd_ >= 0) {
            close(socket_fd_);
            socket_fd_ = -1;
        }
        
        connected_ = false;
    }
    
    void OnConnected() {
        // 连接成功后的处理
        // 发送注册信息等
    }

private:
    std::string host_;
    int port_;
    
    int socket_fd_ = -1;
    std::atomic<bool> connected_;
    std::atomic<bool> should_stop_;
    
    std::unique_ptr<ConnectionKeepalive> keepalive_;
    ReconnectStrategy reconnect_strategy_;
    std::thread connect_thread_;
};

生产环境最佳实践

配置建议

网络类型 心跳间隔 超时时间 最大丢失
有线网络 30s 90s 3
WiFi 20s 60s 3
4G/5G 15s 45s 3
NB-IoT 60s 180s 3

监控指标

cpp 复制代码
/**
 * @brief 连接质量监控
 */
struct ConnectionMetrics {
    int64_t total_heartbeats_sent;
    int64_t total_heartbeats_received;
    int64_t total_timeouts;
    int64_t total_reconnects;
    
    double average_rtt_ms;
    double max_rtt_ms;
    double min_rtt_ms;
    
    std::chrono::system_clock::time_point last_heartbeat_time;
    
    double GetHeartbeatSuccessRate() const {
        if (total_heartbeats_sent == 0) return 0.0;
        return static_cast<double>(total_heartbeats_received) / 
               total_heartbeats_sent * 100.0;
    }
};

告警规则

cpp 复制代码
/**
 * @brief 告警触发条件
 */
bool ShouldAlert(const ConnectionMetrics& metrics) {
    // 心跳成功率低于95%
    if (metrics.GetHeartbeatSuccessRate() < 95.0) {
        return true;
    }
    
    // RTT超过1秒
    if (metrics.average_rtt_ms > 1000) {
        return true;
    }
    
    // 5分钟内重连超过3次
    if (metrics.total_reconnects > 3) {
        return true;
    }
    
    return false;
}

总结

本文详细介绍了C++网络编程中的心跳机制与连接保活:

  1. TCP Keepalive:协议层保活,简单但不够及时
  2. 应用层心跳:灵活可控,生产环境推荐
  3. 心跳策略:固定间隔、自适应频率
  4. 断线重连:指数退避、自动重连
  5. 生产实践:配置建议、监控告警

关键设计决策

决策 选择 理由
心跳类型 应用层为主 可控性高
间隔策略 自适应 兼顾效率和实时性
重连策略 指数退避 避免惊群
检测机制 双向心跳 准确检测

该心跳机制已在AIDC项目中稳定运行,连接可用性达到99.95%


本文基于AIDC项目网络编程实践编写。

https://github.com/0voice

相关推荐
Amumu121382 小时前
Js:正则表达式(二)
开发语言·javascript·正则表达式
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(三十二):SPI 通信深度实战 —— 硬件 SPI 驱动 W25Q64 闪存(底层时序 + 寄存器配置 + 读写封装)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
Sgf2273 小时前
ES8(ES2017)新特性完整指南
开发语言·javascript·ecmascript
好大哥呀3 小时前
C++ Web 编程
开发语言·前端·c++
ID_180079054733 小时前
小红书笔记评论 API,Python 调用示例与完整 JSON 返回参考
java·开发语言
@insist1234 小时前
网络工程师-信道容量计算与 PCM 编码:数据通信核心原理及软考考点解析
网络·网络工程师·pcm·软考·软件水平考试
Mr_Xuhhh4 小时前
LeetCode hot 100(C++版本)(上)
c++·leetcode·哈希算法
漫随流水4 小时前
c++编程:反转字符串(leetcode344)
数据结构·c++·算法
南境十里·墨染春水4 小时前
C++ 笔记 友元(面向对象)
开发语言·c++·笔记