Files
CpCtrl/Udp/ConfigParser.h
2025-06-13 17:35:27 +08:00

269 lines
5.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef CONFIGPARSER_H
#define CONFIGPARSER_H
/**
* 配置文件解析模块
*/
#include <string>
#include <unordered_map>
#include <iostream>
// 平台检测
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <asm-generic/ioctls.h>
#include <sys/ioctl.h>
#endif
#include <iostream>
#include <vector>
#include <functional>
#include <thread>
#include <atomic>
#include <string>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
//定义UDP接收线程超时时间(秒)
#define UDPTimeout (3)
// 平台兼容类型定义
#ifdef _WIN32
using socklen_t = int;
using socket_t = SOCKET;
constexpr socket_t INVALID_SOCKET_VALUE = INVALID_SOCKET;
#else
using socket_t = int;
constexpr socket_t INVALID_SOCKET_VALUE = -1;
#define SOCKET_ERROR (-1)
#endif
// Windows平台初始化
#ifdef _WIN32
class WSAInitializer {
public:
WSAInitializer() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
throw std::runtime_error("WSAStartup failed");
}
}
~WSAInitializer() {
WSACleanup();
}
};
static WSAInitializer wsa_initializer;
#endif
/** 状态码 */
enum CPStatus {
CPSUCCESS = 0,//成功
CPFILE = -1//文件错误
};
/**
* 读取ini类型的配置文件
* @param path 配置文件路径
* @param config 存储配置文件的unordered_map容器
* @return 状态码
*/
CPStatus configFromIni(const std::string &path, std::unordered_map<std::string, std::string> &config);
/**
* UDP基类
*/
class UDPSocketBase {
protected:
UDPSocketBase() : sockfd_(INVALID_SOCKET_VALUE), is_nonblock_(false) {}
/** 创建套接字 */
void create_socket();
void create_socket(socket_t socket);
/** 设置是否阻塞 */
void set_nonblock(bool enable);
/** 建立链接 */
void bind_socket(const sockaddr_in &addr) const;
public:
virtual ~UDPSocketBase();
socket_t sockfd_;
protected:
bool is_nonblock_;
};
/**
* UDP发送端
*/
class UDPSender : public UDPSocketBase {
public:
explicit UDPSender(socket_t socket = INVALID_SOCKET_VALUE, bool nonblock = false);
/** 设置目的地址 */
void set_destination(const std::string &ip, uint16_t port);
/** 设置源地址 */
void set_source(const std::string &ip, uint16_t port);
/** 发送 */
size_t send(const std::vector<uint8_t> &data);
size_t send(uint8_t *data, size_t size);
size_t send(const std::string &data);
std::string dstIp;
uint16_t dstPort;
private:
sockaddr_in dest_addr_{};
};
/**
* UDP接收端
*/
class UDPReceiver : public UDPSocketBase {
public:
/** 处理接收数据函数模板 */
using ReceiveCallback = std::function<void(const std::vector<uint8_t> &, sockaddr_in, socklen_t)>;
/** 设置接收端口 */
explicit UDPReceiver(uint16_t port, bool nonblock = false, size_t buffer_size = 4096);
/** 开始接收线程 */
void start_receiving(const ReceiveCallback &callback);
/** 停止接收线程 */
void stop_receiving();
~UDPReceiver() override;
uint16_t srcPort;
/*UDP接收是否在线*/
std::atomic<bool> isOnline;
private:
/** 接收函数 */
std::pair<ssize_t, std::pair<sockaddr_in, socklen_t>> receive();
private:
std::vector<uint8_t> buffer_;
std::atomic<bool> running_;
std::thread receiver_thread_;
std::thread online_thread_;
std::chrono::time_point<std::chrono::steady_clock> lastTime_;
};
enum LogType {
LTStd,//日志输出到控制台
LTTxt,//日志输出到文本文件
LTUdp,//日志输出到UDP
LTTcp,//日志输出到TCP
};
enum LogLevel {
LLDebug,//调试
LLInfo,//一般
LLWarn,//警告
LLError,//错误
};
class LogL {
public:
/**
* 日志构造函数
* @param logType 日志输出类型
* @param isSync true同步/false异步
* @param logPath 输出地址(LTStd:无;LTTxt:填写路径;LTUdp:填写ip端口)
*/
explicit LogL(LogType logType, bool isSync = true, LogLevel level = LLDebug, std::string logPath = "");
~LogL();
/**
* 调试日志
* @param str 日志内容
*/
void debug(const std::string &str);
void info(const std::string &str);
void warn(const std::string &str);
void error(const std::string &str);
private:
void logThread();
void log(const std::string &str, LogLevel level);
private:
std::thread *m_thread;
bool m_thread_run;
bool m_isSync;//是否同步
LogType m_logType;//输出类型
LogLevel m_logLevel;//输出级别
std::string m_logPath;//输出地址
std::queue<std::string> m_log_queue;//日志容器
std::mutex m_mtx;
std::condition_variable m_cond_empty;//空时停止
std::condition_variable m_cond_full;//满时停止
std::ofstream *m_file;
int32_t m_today;
std::unique_ptr<UDPSender> m_sender;
};
/**
* 创建目录
* @param path 路径
* @return bool是否创建成功
*/
bool myMkdir(const char *path);
/**
* 获取当前日期时间
*/
class myDateTime {
public:
myDateTime();
int32_t year;
int32_t month;
int32_t day;
int32_t hour;
int32_t minute;
int32_t second;
std::string toDate() const;
std::string toTime() const;
std::string toDateTime() const;
};
#endif //CONFIGPARSER_H