add old lci module

This commit is contained in:
qing committed 2026-08-02 20:15:07 +08:00
1 parent 38a6e815f0
commit 8499631091
171 files changed
+25562

No files matched your search

+82
View File
@@ -0,0 +1,82 @@
#pragma once
#include <httplib.h> // libcpp-httplib-dev
#include <nlohmann/json.hpp> //
#include <iostream>
#include <filesystem> //
#include <stdexcept>
namespace fs = std::filesystem;
/* 这里的类型是HTTP服务器要设置的回调函数的类型 */
using Handler = std::function<void(const httplib::Request&, httplib::Response&)>;
namespace qing {
/* NOTE: 不要删除该类,这个抽象成能够方便重构 */
class Http { /* 超文本传输协议(HTTP)服务器类 */
public:
/* 初始化各个变量 */
Http(std::string addr, int port): addr(addr), port(port) {}
/* 运行服务器,失败抛出异常 */
void run() {
//printAddr(); /* 在日志里打印更好 */
if (!svr.listen(addr.c_str(), port))
throw StartServerFailed("");
}
/* 终止服务器 */
void stop() { svr.stop(); }
/*
* 设置路由和对应的处理函数
*
* FIXME: 使用一个方法实现两个功能
*/
void get (std::string path, Handler handler) { svr.Get(path, handler); }
void post(std::string path, Handler handler) { svr.Post(path, handler); }
/*
* 打印地址
*
* FIXME: 把这个函数的具体功能放到类的外部
*/
std::string printAddr() { return std::string("pmcd now listenning on this address: http://") + addr + ":" + std::to_string(port); }
/* 获取当前执行文件目录 */
//static std::string getCurrentDirectory() {
// fs::path currentPath = fs::absolute(__FILE__);
// return currentPath.parent_path().string();
//}
// 读取文本文件的所有内容
//static std::string readFile(const std::string& filePath) {
// std::ifstream file(filePath); // 创建一个输入文件流对象,用于读取文件
// if (!file) {
// std::cerr << "无法打开文件:" << filePath << std::endl;
// return "";
// }
// std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); /* 使用迭代器读取文件内容到字符串 */
// file.close();
// return content;
//}
class Http_Error: public std::exception { /* HTTP 异常类 */
private:
std::string message;
public:
explicit Http_Error(const std::string& msg): message(msg) {}
const char* what() const noexcept override {
return message.c_str();
}
};
class StartServerFailed: public Http_Error { /* 开始服务失败 */
public:
StartServerFailed(const std::string& msg): Http_Error(msg) {}
};
private:
httplib::Server svr; /* 创建HTTP服务器对象(如果需要HTTPS,则使用SSLServer */
std::string addr; /* 服务地址 */
int port; /* 端口 */
};
}
+151
View File
@@ -0,0 +1,151 @@
#ifndef PMC_HTTP_CLIENT_HPP
#define PMC_HTTP_CLIENT_HPP
#include <string>
#include <functional>
#include <curl/curl.h>
#include <iostream>
namespace pmc::net {
class HttpClient {
public:
HttpClient() {
std::cout << "HttpClient构造函数: 开始初始化" << std::endl;
curl_ = curl_easy_init();
if (!curl_) {
throw std::runtime_error("Failed to initialize CURL");
}
std::cout << "HttpClient构造函数: 初始化完成" << std::endl;
}
~HttpClient() {
std::cout << "HttpClient析构函数: 开始清理" << std::endl;
if (curl_) {
curl_easy_cleanup(curl_);
}
if (headers_) {
curl_slist_free_all(headers_);
}
std::cout << "HttpClient析构函数: 清理完成" << std::endl;
}
void set_header(const std::string& header) {
std::cout << "set_header: 添加header: " << header << std::endl;
headers_ = curl_slist_append(headers_, header.c_str());
}
// 同步流式请求
void post_stream_sync(const std::string& url, const std::string& data, std::function<void(const std::string&)> callback) {
std::cout << "post_stream_sync: 开始发送流式请求到 " << url << std::endl;
if (!curl_) {
throw std::runtime_error("CURL not initialized");
}
// 重置CURL句柄
curl_easy_reset(curl_);
// 设置URL
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
// 设置POST请求
curl_easy_setopt(curl_, CURLOPT_POST, 1L);
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, data.size());
// 设置请求头
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers_);
// 设置流式回调函数
std::string buffer;
auto data_pair = std::make_pair(&buffer, &callback);
std::cout << "post_stream_sync: 数据对创建完成" << std::endl;
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, stream_write_callback);
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &data_pair);
// 设置超时和连接选项
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 30L);
curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 10L);
// 执行请求
std::cout << "post_stream_sync: 执行请求" << std::endl;
CURLcode res = curl_easy_perform(curl_);
std::cout << "post_stream_sync: 数据对清理完成" << std::endl;
if (res != CURLE_OK) {
std::cout << "post_stream_sync: CURL错误: " << curl_easy_strerror(res) << std::endl;
throw std::runtime_error(std::string("CURL error: ") + curl_easy_strerror(res));
}
std::cout << "post_stream_sync: 请求成功" << std::endl;
}
private:
CURL* curl_ = nullptr;
struct curl_slist* headers_ = nullptr;
static size_t stream_write_callback(char* ptr, size_t size, size_t nmemb, void* userdata) {
// userdata指向一个std::pair<std::string*, std::function<void(const std::string&)>*>
auto* data_pair = static_cast<std::pair<std::string*, std::function<void(const std::string&)>*>*>(userdata);
if (!data_pair || !data_pair->first || !data_pair->second) {
std::cout << "stream_write_callback: 无效的用户数据" << std::endl;
return 0;
}
std::string& buffer = *(data_pair->first);
std::function<void(const std::string&)>& callback = *(data_pair->second);
size_t total_size = size * nmemb;
std::cout << "stream_write_callback: 收到 " << total_size << " 字节数据" << std::endl;
// 将数据追加到缓冲区
buffer.append(ptr, total_size);
// 打印原始数据(用于调试)
std::string raw_data(ptr, total_size);
std::cout << "stream_write_callback: 原始数据: " << raw_data << std::endl;
// 处理流式数据(按行处理Server-Sent Events格式)
size_t pos = 0;
size_t newline_pos;
while ((newline_pos = buffer.find('\n', pos)) != std::string::npos) {
std::string line = buffer.substr(pos, newline_pos - pos);
pos = newline_pos + 1;
std::cout << "stream_write_callback: 处理行: " << line << std::endl;
// 处理SSE格式的数据(以"data: "开头)
if (line.rfind("data: ", 0) == 0) {
std::string json_str = line.substr(6);
if (json_str == "[DONE]") {
std::cout << "stream_write_callback: 收到 [DONE]" << std::endl;
callback("[[流式传输完成]]");
continue;
}
// 调用回调函数处理JSON数据
std::cout << "stream_write_callback: 调用回调,数据长度: " << json_str.length() << std::endl;
callback(json_str);
} else if (!line.empty()) {
// 如果不是SSE格式,直接传递给回调(可能是错误消息)
std::cout << "stream_write_callback: 非SSE数据,直接传递: " << line << std::endl;
callback(line);
}
}
// 移除已处理的数据
if (pos > 0) {
buffer.erase(0, pos);
}
return total_size;
}
};
} // namespace pmc::net
#endif // PMC_HTTP_CLIENT_HPP
+193
View File
@@ -0,0 +1,193 @@
#ifndef HTTPSERVER_HPP
#define HTTPSERVER_HPP
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/config.hpp>
#include <memory>
#include <string>
#include <functional>
#include <unordered_map>
#include <vector>
#include <iostream>
#include <thread>
#include <atomic>
namespace beast = boost::beast;
namespace http = beast::http;
namespace asio = boost::asio;
using tcp = boost::asio::ip::tcp;
namespace pmc {
namespace net {
/**
* @brief HTTP请求处理器类型定义
*
* 处理HTTP请求并返回响应
*/
using HttpRequestHandler = std::function<http::response<http::string_body>(
const http::request<http::string_body>&,
const std::unordered_map<std::string, std::string>&)>;
/**
* @brief 中间件处理器类型定义
*
* 用于处理请求链的中间件
*/
using MiddlewareHandler = std::function<bool(
const http::request<http::string_body>&,
http::response<http::string_body>&,
const std::unordered_map<std::string, std::string>&)>;
/**
* @brief HTTP服务器类(合并增强版)
*
* 基于boost::asio和boost::beast的异步HTTP服务器
* 结合了原始版本的易用性和修复版本的功能完整性
*/
class HttpServer {
public:
/**
* @brief 构造函数(监听所有接口)
* @param port 监听端口
* @param threads 工作线程数
*/
explicit HttpServer(unsigned short port, unsigned int threads = 1);
/**
* @brief 构造函数(指定监听地址)
* @param address 监听IP地址(如 "0.0.0.0" 或 "127.0.0.1")
* @param port 监听端口
* @param threads 工作线程数
*/
explicit HttpServer(const std::string& address, unsigned short port, unsigned int threads = 1);
/**
* @brief 析构函数
*/
~HttpServer();
/**
* @brief 启动服务器
*/
void start();
/**
* @brief 停止服务器
*/
void stop();
/**
* @brief 注册GET请求处理器
* @param path 请求路径
* @param handler 请求处理器
*/
void get(const std::string& path, HttpRequestHandler handler);
/**
* @brief 注册POST请求处理器
* @param path 请求路径
* @param handler 请求处理器
*/
void post(const std::string& path, HttpRequestHandler handler);
/**
* @brief 注册PUT请求处理器
* @param path 请求路径
* @param handler 请求处理器
*/
void put(const std::string& path, HttpRequestHandler handler);
/**
* @brief 注册DELETE请求处理器
* @param path 请求路径
* @param handler 请求处理器
*/
void del(const std::string& path, HttpRequestHandler handler);
/**
* @brief 注册中间件
* @param middleware 中间件处理器
*/
void use(MiddlewareHandler middleware);
/**
* @brief 设置静态文件目录
* @param path 静态文件目录路径
*/
void setStaticDirectory(const std::string& path);
/**
* @brief 获取服务器状态
* @return 服务器是否正在运行
*/
bool isRunning() const;
/**
* @brief 获取服务器端口
* @return 服务器监听端口
*/
unsigned short getPort() const;
/**
* @brief 获取服务器监听地址
* @return 服务器监听地址
*/
std::string getAddress() const;
/**
* @brief 运行服务器(阻塞调用)- 从原始版本继承
*/
void run();
/**
* @brief 显示服务器状态信息 - 从原始版本继承
*/
void showStatus() const;
private:
// 内部类声明
class Session;
class Listener;
// 服务器配置
std::string address_;
unsigned short port_;
unsigned int threads_;
std::atomic<bool> running_{false};
// Boost.Asio上下文
std::unique_ptr<asio::io_context> ioc_;
// 网络组件
std::shared_ptr<Listener> listener_;
std::vector<std::thread> worker_threads_;
// 路由表
std::unordered_map<std::string, HttpRequestHandler> get_handlers_;
std::unordered_map<std::string, HttpRequestHandler> post_handlers_;
std::unordered_map<std::string, HttpRequestHandler> put_handlers_;
std::unordered_map<std::string, HttpRequestHandler> delete_handlers_;
// 中间件链
std::vector<MiddlewareHandler> middlewares_;
// 静态文件目录
std::string static_directory_;
// 内部方法
std::unordered_map<std::string, std::string> parseQueryParams(const std::string& query);
// 请求处理
http::response<http::string_body> handleRequest(const http::request<http::string_body>& req);
};
} // namespace net
} // namespace pmc
#endif // HTTPSERVER_HPP
+63
View File
@@ -0,0 +1,63 @@
#ifndef PMC_NET_WEBSOCKET_CLIENT_HPP
#define PMC_NET_WEBSOCKET_CLIENT_HPP
#include "WebSocketClientBase.hpp"
namespace pmc {
namespace net {
/**
* @brief 基于 Boost.Beast 的异步 WebSocket 客户端(非 SSL 版本)
*/
class WebSocketClient : public WebSocketClientBase {
public:
/**
* @brief 构造函数
* @param host 服务器主机名或 IP 地址
* @param port 服务器端口号
* @param path WebSocket 路径(默认 "/")
*/
WebSocketClient(const std::string& host, const std::string& port, const std::string& path = "/");
/**
* @brief 析构函数
*/
~WebSocketClient();
// 实现 WebSocketClientBase 接口
void setMessageCallback(MessageCallback callback) override;
void setErrorCallback(ErrorCallback callback) override;
void setConnectCallback(ConnectCallback callback) override;
void setCloseCallback(CloseCallback callback) override;
bool connect(int timeout_ms = 5000) override;
void disconnect() override;
bool isConnected() const override;
bool send(const std::string& message) override;
bool sendBinary(const void* data, size_t size) override;
void setAutoReconnect(bool enable, int interval_ms = 3000) override;
void setHeartbeatInterval(int interval_ms = 30000) override;
std::string getHost() const override;
std::string getPort() const override;
std::string getPath() const override;
// SSL/TLS 相关(非 SSL 版本返回默认值)
bool isSecure() const override { return false; }
void setVerifyCertificate(bool verify) override { /* 忽略 */ }
void setCertificateFile(const std::string& cert_file) override { /* 忽略 */ }
void setPrivateKeyFile(const std::string& key_file) override { /* 忽略 */ }
void setCertificateAuthorityFile(const std::string& ca_file) override { /* 忽略 */ }
private:
// 前向声明实现类
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace net
} // namespace pmc
#endif // PMC_NET_WEBSOCKET_CLIENT_HPP
+61
View File
@@ -0,0 +1,61 @@
#ifndef PMC_NET_WEBSOCKET_CLIENT_BASE_HPP
#define PMC_NET_WEBSOCKET_CLIENT_BASE_HPP
#include <string>
#include <functional>
#include <memory>
namespace pmc {
namespace net {
/**
* @brief WebSocket 客户端基类
*
* 定义所有 WebSocket 客户端的公共接口
*/
class WebSocketClientBase {
public:
// 回调函数类型
using MessageCallback = std::function<void(const std::string&)>;
using ErrorCallback = std::function<void(const std::string&)>;
using ConnectCallback = std::function<void(bool)>;
using CloseCallback = std::function<void()>;
virtual ~WebSocketClientBase() = default;
// 回调函数设置
virtual void setMessageCallback(MessageCallback callback) = 0;
virtual void setErrorCallback(ErrorCallback callback) = 0;
virtual void setConnectCallback(ConnectCallback callback) = 0;
virtual void setCloseCallback(CloseCallback callback) = 0;
// 连接管理
virtual bool connect(int timeout_ms = 5000) = 0;
virtual void disconnect() = 0;
virtual bool isConnected() const = 0;
// 消息发送
virtual bool send(const std::string& message) = 0;
virtual bool sendBinary(const void* data, size_t size) = 0;
// 配置选项
virtual void setAutoReconnect(bool enable, int interval_ms = 3000) = 0;
virtual void setHeartbeatInterval(int interval_ms = 30000) = 0;
// 信息获取
virtual std::string getHost() const = 0;
virtual std::string getPort() const = 0;
virtual std::string getPath() const = 0;
// SSL/TLS 相关
virtual bool isSecure() const = 0;
virtual void setVerifyCertificate(bool verify) = 0;
virtual void setCertificateFile(const std::string& cert_file) = 0;
virtual void setPrivateKeyFile(const std::string& key_file) = 0;
virtual void setCertificateAuthorityFile(const std::string& ca_file) = 0;
};
} // namespace net
} // namespace pmc
#endif // PMC_NET_WEBSOCKET_CLIENT_BASE_HPP
+85
View File
@@ -0,0 +1,85 @@
#ifndef PMC_NET_WEBSOCKET_CLIENT_SSL_HPP
#define PMC_NET_WEBSOCKET_CLIENT_SSL_HPP
#include "WebSocketClientBase.hpp"
#include <string>
#include <memory>
namespace pmc {
namespace net {
/**
* @brief 基于 Boost.Beast 的异步 WebSocket 客户端(SSL/TLS 版本)
*
* 支持安全的 WebSocket 连接(wss://)
*/
class WebSocketClientSSL : public WebSocketClientBase {
public:
/**
* @brief 构造函数
* @param host 服务器主机名或 IP 地址
* @param port 服务器端口号(通常为 443)
* @param path WebSocket 路径(默认 "/")
*/
WebSocketClientSSL(const std::string& host, const std::string& port, const std::string& path = "/");
/**
* @brief 析构函数
*/
~WebSocketClientSSL();
// 实现 WebSocketClientBase 接口
void setMessageCallback(MessageCallback callback) override;
void setErrorCallback(ErrorCallback callback) override;
void setConnectCallback(ConnectCallback callback) override;
void setCloseCallback(CloseCallback callback) override;
bool connect(int timeout_ms = 5000) override;
void disconnect() override;
bool isConnected() const override;
bool send(const std::string& message) override;
bool sendBinary(const void* data, size_t size) override;
void setAutoReconnect(bool enable, int interval_ms = 3000) override;
void setHeartbeatInterval(int interval_ms = 30000) override;
std::string getHost() const override;
std::string getPort() const override;
std::string getPath() const override;
// SSL/TLS 相关方法
bool isSecure() const override { return true; }
void setVerifyCertificate(bool verify) override;
void setCertificateFile(const std::string& cert_file) override;
void setPrivateKeyFile(const std::string& key_file) override;
void setCertificateAuthorityFile(const std::string& ca_file) override;
/**
* @brief 设置 SSL 上下文选项
* @param options SSL 上下文选项
*/
void setSSLContextOptions(long options);
/**
* @brief 设置密码列表
* @param ciphers 密码列表字符串
*/
void setCiphers(const std::string& ciphers);
/**
* @brief 设置 SNI 主机名
* @param sni_hostname SNI 主机名
*/
void setSNIHostname(const std::string& sni_hostname);
private:
// 前向声明实现类
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace net
} // namespace pmc
#endif // PMC_NET_WEBSOCKET_CLIENT_SSL_HPP
+176
View File
@@ -0,0 +1,176 @@
// WebSocketServer.hpp - WebSocket服务器头文件
// 基于Boost.Beast和Boost.Asio
#ifndef PMC_NET_WEBSOCKETSERVER_HPP
#define PMC_NET_WEBSOCKETSERVER_HPP
#include <functional>
#include <string>
#include <memory>
#include <unordered_map>
#include <mutex>
#include <atomic>
#include <vector>
#include <thread>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
namespace pmc::net {
/**
* @brief WebSocket连接处理器类型定义
*
* 处理WebSocket连接建立后的消息收发
*/
using WebSocketMessageHandler = std::function<void(
const std::string& clientId,
const std::string& message,
std::function<void(const std::string&)> sendCallback)>;
/**
* @brief WebSocket连接回调类型定义
*/
using WebSocketConnectHandler = std::function<void(
const std::string& clientId,
const std::string& remoteAddress)>;
/**
* @brief WebSocket断开连接回调类型定义
*/
using WebSocketDisconnectHandler = std::function<void(
const std::string& clientId)>;
/**
* @brief WebSocket服务器类
*
* 基于Boost.Beast和Boost.Asio实现的WebSocket服务器
*/
class WebSocketServer {
public:
/**
* @brief 构造函数
* @param port 监听端口
* @param threads 线程数(默认2)
*/
WebSocketServer(unsigned short port, unsigned int threads = 2);
/**
* @brief 析构函数
*/
~WebSocketServer();
/**
* @brief 启动服务器
*/
void start();
/**
* @brief 停止服务器
*/
void stop();
/**
* @brief 注册消息处理器
* @param path 路径(用于路由)
* @param handler 消息处理器
*/
void onMessage(const std::string& path, WebSocketMessageHandler handler);
/**
* @brief 注册连接处理器
* @param handler 连接处理器
*/
void onConnect(WebSocketConnectHandler handler);
/**
* @brief 注册断开连接处理器
* @param handler 断开连接处理器
*/
void onDisconnect(WebSocketDisconnectHandler handler);
/**
* @brief 向指定客户端发送消息
* @param clientId 客户端ID
* @param message 消息内容
* @return 是否发送成功
*/
bool sendToClient(const std::string& clientId, const std::string& message);
/**
* @brief 向所有客户端广播消息
* @param message 消息内容
* @return 成功发送的客户端数量
*/
size_t broadcast(const std::string& message);
/**
* @brief 断开指定客户端连接
* @param clientId 客户端ID
*/
void disconnectClient(const std::string& clientId);
/**
* @brief 获取当前连接的客户端数量
* @return 客户端数量
*/
size_t getClientCount() const;
/**
* @brief 获取服务器是否正在运行
* @return 运行状态
*/
bool isRunning() const { return running_; }
/**
* @brief 获取服务器监听端口
* @return 端口号
*/
unsigned short getPort() const { return port_; }
private:
// 内部Session类
class Session;
// 内部Listener类
class Listener;
// 内部实现结构体
struct Impl {
boost::asio::io_context ioc_;
std::shared_ptr<Listener> listener_;
std::vector<std::thread> threads_;
};
// 服务器配置
unsigned short port_;
unsigned int threads_;
std::atomic<bool> running_{false};
// 内部实现
std::unique_ptr<Impl> impl_;
// 生成客户端ID
std::string generateClientId() const;
// 添加客户端
void addClient(const std::string& clientId, std::shared_ptr<Session> session);
// 移除客户端
void removeClient(const std::string& clientId);
// 获取客户端Session
std::shared_ptr<Session> getClient(const std::string& clientId);
// 回调函数
std::unordered_map<std::string, WebSocketMessageHandler> messageHandlers_;
WebSocketConnectHandler connectHandler_;
WebSocketDisconnectHandler disconnectHandler_;
// 客户端管理
mutable std::mutex clientsMutex_;
std::unordered_map<std::string, std::shared_ptr<Session>> clients_;
};
} // namespace pmc::net
#endif // PMC_NET_WEBSOCKETSERVER_HPP