Files
CpCtrl/Udp/ConfigParser.h

269 lines
5.4 KiB
C
Raw Normal View History

2025-06-12 15:28:37 +08:00
#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