HTTP实现心跳模块

HTTP实现心跳模块

使用轻量级的c++HTTP库cpp-httplib重现实现HTTP心跳模块

头文件HttplibHeartbeat.h

cpp 复制代码
#ifndef HTTPLIB_HEARTBEAT_H
#define HTTPLIB_HEARTBEAT_H

#include <string>
#include <thread>
#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include "httplib.h"
#include "json.hpp"、

using json = nlohmann::json;

class HttplibHeartbeat {
public:
    using ResponseCallback = std::function<void(const std::string& response, bool success)>;
    
    /**
     * @brief 构造函数
     * @param host 服务器主机名或IP
     * @param port 服务器端口
     * @param endpoint 心跳端点路径
     * @param interval 心跳间隔(秒)
     */
    HttplibHeartbeat(const std::string& host, int port, 
                    const std::string& endpoint, unsigned int interval);
    
    /** 
     * @param heartbeat_data 心跳数据(将转换为JSON)
     */
    HttplibHeartbeat(const std::string& host, int port, 
                 const std::string& endpoint, unsigned int interval,
                 const std::map<std::string, std::string>& heartbeat_data);
    
    ~HttplibHeartbeat();
    
    void start(ResponseCallback callback);
    void stop();
    void setInterval(unsigned int interval);
    bool isRunning() const;
    void updateHeartbeatData(const std::map<std::string, std::string>& new_data);

private:
    void heartbeatLoop();
    json createHeartbeatJson() const;
    
    std::string m_host;
    int m_port;
    std::string m_endpoint;
    unsigned int m_interval;
    std::atomic<bool> m_running;
    std::thread m_thread;
    ResponseCallback m_callback;
    std::unique_ptr<httplib::Client> m_client;
    std::map<std::string, std::string> m_heartbeat_data;
};

#endif // HTTPLIB_HEARTBEAT_H

cpp源文件 HttplibHeartbeat.cpp

cpp 复制代码
#include "HttplibHeartbeat.h"
#include <iostream>

HttplibHeartbeat::HttplibHeartbeat(const std::string& host, int port, 
                                  const std::string& endpoint, unsigned int interval)
    : m_host(host), m_port(port), m_endpoint(endpoint), 
      m_interval(interval), m_running(false) {
    
    m_client = std::make_unique<httplib::Client>(host, port);
    // 设置超时时间
    m_client->set_connection_timeout(3); // 3秒连接超时
    m_client->set_read_timeout(5);       // 5秒读取超时
}

HttplibHeartbeat::HttplibHeartbeat(const std::string& host, int port, 
                           const std::string& endpoint, unsigned int interval,
                           const std::map<std::string, std::string>& heartbeat_data)
    : m_host(host), m_port(port), m_endpoint(endpoint), 
      m_interval(interval), m_running(false),
      m_heartbeat_data(heartbeat_data) {
    
    m_client = std::make_unique<httplib::Client>(host, port);
    m_client->set_connection_timeout(3);
    m_client->set_read_timeout(5);
}

HttplibHeartbeat::~HttplibHeartbeat() {
    stop();
}

void HttplibHeartbeat::start(ResponseCallback callback) {
    if (m_running) {
        return;
    }
    
    m_callback = callback;
    m_running = true;
    m_thread = std::thread(&HttplibHeartbeat::heartbeatLoop, this);
}

void HttplibHeartbeat::stop() {
    if (!m_running) {
        return;
    }
    
    m_running = false;
    if (m_thread.joinable()) {
        m_thread.join();
    }
}

void HttplibHeartbeat::setInterval(unsigned int interval) {
    m_interval = interval;
}

bool HttplibHeartbeat::isRunning() const {
    return m_running;
}

void HttplibHeartbeat::updateHeartbeatData(const std::map<std::string, std::string>& new_data) {
    m_heartbeat_data = new_data;
}

void HttplibHeartbeat::heartbeatLoop() {
    while (m_running) {
        std::string response;
        bool success = false;
        
        if (auto res = m_client->Get(m_endpoint.c_str())) {
            if (res->status == 200) {
                response = res->body;
                success = true;
            } else {
                response = "HTTP status: " + std::to_string(res->status);
            }
        } else {
            response = "Error: " + httplib::to_string(res.error());
        }
        
        if (m_callback) {
            m_callback(response, success);
        }
        
        // 等待下一次心跳
        for (unsigned int i = 0; i < m_interval && m_running; ++i) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
}
/*
void HttplibHeartbeat::heartbeatLoop() {
    while (m_running) {
        json response_json;
        bool success = false;
        
        // 创建心跳JSON数据
        json request_json = createHeartbeatJson();
        std::string request_body = request_json.dump();
        
        // 设置JSON内容类型头
        httplib::Headers headers = {
            {"Content-Type", "application/json"}
        };
        
        if (auto res = m_client->Post(m_endpoint.c_str(), headers, request_body, "application/json")) {
            if (res->status == 200) {
                try {
                    response_json = json::parse(res->body);
                    success = true;
                } catch (const json::parse_error& e) {
                    response_json = {
                        {"error", "Failed to parse server response"},
                        {"details", e.what()},
                        {"raw_response", res->body}
                    };
                }
            } else {
                response_json = {
                    {"error", "HTTP request failed"},
                    {"status", res->status},
                    {"body", res->body}
                };
            }
        } else {
            response_json = {
                {"error", "Network error"},
                {"details", httplib::to_string(res.error())}
            };
        }
        
        if (m_callback) {
            m_callback(response_json, success);
        }
        
        // 等待下一次心跳
        for (unsigned int i = 0; i < m_interval && m_running; ++i) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
}
*/
json HttplibHeartbeat::createHeartbeatJson() const {
    json j;
    j["type"] = "heartbeat";
    j["timestamp"] = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::system_clock::now().time_since_epoch()).count();
    
    // 添加自定义心跳数据
    for (const auto& [key, value] : m_heartbeat_data) {
        j[key] = value;
    }
    
    return j;
}

使用实例

cpp 复制代码
#include "HttplibHeartbeat.h"
#include <iostream>

int main() {
    // 创建心跳对象,连接localhost:8080,每5秒发送一次心跳
    HttplibHeartbeat heartbeat("localhost", 8080, "/api/heartbeat", 5);
    
    // 定义回调函数
    auto callback = [](const std::string& response, bool success) {
        if (success) {
            std::cout << "[Heartbeat] Success: " << response << std::endl;
        } else {
            std::cerr << "[Heartbeat] Failed: " << response << std::endl;
        }
    };
    
  /*  
    // 准备心跳数据
    std::map<std::string, std::string> heartbeat_data = {
        {"device_id", "12345"},
        {"version", "1.0.0"},
        {"status", "active"}
    };
    
    // 创建JSON心跳对象
    HttplibHeartbeat heartbeat("localhost", 8080, "/api/heartbeat", 10, heartbeat_data);
    // 定义回调函数
    auto callback = [](const json& response, bool success) {
        if (success) {
            std::cout << "[Heartbeat] Success. Server response:" << std::endl;
            std::cout << response.dump(4) << std::endl; // 漂亮打印JSON
            
            // 可以解析特定字段
            if (response.contains("next_check_interval")) {
                std::cout << "Next check in: " << response["next_check_interval"] << "s" << std::endl;
            }
        } else {
            std::cerr << "[Heartbeat] Failed. Error response:" << std::endl;
            std::cerr << response.dump(4) << std::endl;
        }
    };
    */
    
    // 启动心跳
    heartbeat.start(callback);
    
    std::cout << "Heartbeat started. Press Enter to stop..." << std::endl;
    std::cin.get();
    
    // 停止心跳
    heartbeat.stop();
    
    return 0;
}

编译说明

  1. 下载 cpp-httplib 头文件
  2. httplib.h 放在项目目录中
  3. 编译命令示例:g++ -std=c++11 HttplibHeartbeat.cpp main.cpp -lpthread -o heartbeat
相关推荐
惜.己42 分钟前
appium中urllib3.exceptions.LocationValueError: No host specified. 的错误解决办法
网络·appium
吉凶以情迁1 小时前
window服务相关问题探索 go语言服务开发探索调试
linux·服务器·开发语言·网络·golang
专注VB编程开发20年1 小时前
UDP受限广播地址255.255.255.255的通信机制详解
网络·udp·智能路由器
189228048612 小时前
NX947NX955美光固态闪存NX962NX966
大数据·服务器·网络·人工智能·科技
Sadsvit3 小时前
Linux 进程管理与计划任务
linux·服务器·网络
一碗白开水一4 小时前
【模型细节】FPN经典网络模型 (Feature Pyramid Networks)详解及其变形优化
网络·人工智能·pytorch·深度学习·计算机视觉
什么都想学的阿超4 小时前
【网络与爬虫 38】Apify全栈指南:从0到1构建企业级自动化爬虫平台
网络·爬虫·自动化
D-海漠5 小时前
安全光幕Muting功能程序逻辑设计
服务器·网络·人工智能
都给我6 小时前
可计算存储(Computational Storage)与DPU(Data Processing Unit)的技术特点对比及实际应用场景分析
运维·服务器·网络·云计算
阿蒙Amon7 小时前
详解Python标准库之互联网数据处理
网络·数据库·python