#ifndef CONFIGPARSER_H #define CONFIGPARSER_H /** * 配置文件解析模块 */ #include #include #include // 平台检测 #ifdef _WIN32 #include #include #else #include #include #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include //定义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 &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 &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 &, 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 isOnline; private: /** 接收函数 */ std::pair> receive(); private: std::vector buffer_; std::atomic running_; std::thread receiver_thread_; std::thread online_thread_; std::chrono::time_point 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 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 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