Glog 基于 UDP 的封装实现
下面是一个基于 UDP 协议实现的简单日志库(Glog-like)的完整代码,包含测试示例。
1. 头文件 udp_logger.h
#ifndef UDP_LOGGER_H
#define UDP_LOGGER_H
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <ctime>
#include <sstream>
class UdpLogger {
public:
enum Severity {
INFO,
WARNING,
ERROR,
FATAL
};
// 构造函数,指定目标IP和端口
UdpLogger(const std::string& ip, int port);
// 析构函数
~UdpLogger();
// 日志记录函数
void Log(Severity severity, const std::string& message);
// 便捷方法
void Info(const std::string& message);
void Warning(const std::string& message);
void Error(const std::string& message);
void Fatal(const std::string& message);
private:
int sockfd_;
struct sockaddr_in server_addr_;
// 获取当前时间字符串
std::string GetCurrentTime();
// 获取严重级别字符串
std::string GetSeverityString(Severity severity);
};
#endif // UDP_LOGGER_H
2. 实现文件 udp_logger.cpp
#include "udp_logger.h"
#include <iostream>
UdpLogger::UdpLogger(const std::string& ip, int port) {
// 创建UDP套接字
sockfd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd_ == -1) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
// 设置服务器地址结构体
memset(&server_addr_, 0, sizeof(server_addr_));
server_addr_.sin_family = AF_INET;
server_addr_.sin_port = htons(port);
if (inet_pton(AF_INET, ip.c_str(), &server_addr_.sin_addr) <= 0) {
perror("Invalid address/Address not supported");
close(sockfd_);
exit(EXIT_FAILURE);
}
}
UdpLogger::~UdpLogger() {
if (sockfd_ != -1) {
close(sockfd_);
}
}
std::string UdpLogger::GetCurrentTime() {
std::time_t now = time(nullptr);
std::tm* tm_now = localtime(&now);
char buffer[80];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_now);
return buffer;
}
std::string UdpLogger::GetSeverityString(Severity severity) {
switch (severity) {
case INFO: return "INFO";
case WARNING: return "WARNING";
case ERROR: return "ERROR";
case FATAL: return "FATAL";
default: return "UNKNOWN"; } }
void UdpLogger::Log(Severity severity, const std::string& message) {
std::ostringstream oss;
oss << "[" << GetCurrentTime() << "] [" << GetSeverityString(severity) << "] "
<< message;
std::string log_message = oss.str();
int ret = sendto(sockfd_, log_message.c_str(), log_message.size(), MSG_CONFIRM,
(const struct sockaddr*)&server_addr_, sizeof(server_addr_));
if (ret == -1) {
perror("Failed to send log");
close(sockfd_);
exit(EXIT_FAILURE); } }
void UdpLogger::Info(const std::string& message) { Log(INFO, message); }
void UdpLogger::Warning(const std :: string &message ){ Log(WARNING ,message );}
void UdpLogger ::Error(const std :: string &message ){ Log(ERROR ,message );}
void UdpLogger ::Fatal(const std :: string &message ){ Log(FATAL ,message );}
3. UDP日志接收服务器 udp_log_server.cpp
#include <iostream> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> #include<cstring>
#define BUFFER_SIZE 1024
int main(int argc ,char **argv){
if(argc !=2){ printf("Usage :%s [port]\n",argv[0]); exit(-1);}
int port=atoi(argv[1]);
int sock=socket(AF_INET,SOCK_DGRAM ,IPPROTO_UDP );
struct sockaddr_in addr={}; memset(&addr,'\0',sizeof(struct sockaddr_in)); addr.sin_family=AF_INET ; addr.sin_port=htons((unsigned short)(port)) ; addr.sin_addr.s_addr=htonl(INADDR_ANY ) ; bind(sock,(struct sockaddr *) &addr,sizeof(struct sockaddr_in )) ;
char buf[BUFFER_SIZE ]={}; while(true){ struct sockaddr_in client={}; memset(&client,'\0',sizeof(client )) ; unsigned len=sizeof(client )) ; recvfrom(sock,buf,BUFFER_SIZE-1,NULL,(struct sockaddrr *) &client,&len )) ;
printf("%s\n",buf );
memset(buf,'\0',BUFFER_SIZE )) ;
sleep(.5f );
}}//end main()
##4.测试程序 test.cpp
# include"udplogger.hpp"
# include<iostream >
using namespace st d;
intmain(){ try{
/*创建logger实例*/
UpdLoggerglogger ("127 .0 .0 .1 ",9999 );
/*发送不同级别的日志*/
g logger.Informational ("This is an informational messag e." );
g logger.Warning ("This is a warning messag e." );
g logger.Error ("This is an error messag e." );
g logger.Fatal ("This is a fatal messag e." );
cout<<"All logs sent successfully!"<<endl ;
}catch(... ){
cerr<<"Exception occurred while sending logs!"<<endl ;
return-10 ;
}//end try-catch block.
return00 ;
}//end main function.
##5.Makefile文件内容如下:
all : server client test clean run_server run_client run_test
run_server :
./udpserver.exe &
run_client :
./testclient.exe &
run_test :
./testapp.exe &
clean :
rm-rf *.o *.exe *~
%.o : %. cpp $(CXX)-c$<-o$@ $(CFLAGS )
udpserver.exe : udpserver.o $(CXX)$^-o$@ $(LDFLAGS )
testclient.exe : testclient.o updlogger.o $(CXX)$^-o$@ $(LDFLAGS )
testapp.exe : testapp.o updlogger.o $(CXX)$^-o$@ $(LDFLAGS )
##6.编译运行步骤说明:
###6.1编译并启动服务端程序:
g++ -std=c++11 -Wall -pedantic errors.cpp -o errors && ./errors &
或者直接执行:
make run_server PORT=9999 &
其中PORT参数可以修改为你想要监听的端口号。
###6.2编译并启动客户端程序:
g++ --std=c++11 --Wall --pedantic testclient.cpp updlogger.cpp – o testclient && ./testclien t…
或者直接执行:
make run_clien t…
###6.3查看输出结果: 服务端会打印出类似以下格式的内容: “[2023-03-15T14:25:36] [INFO] Thisisaninformationalmessage.” “[2023–03–15T14:25:36][WARNI NG] Thisisawarningmessage.” “[2023–03–15T14:25:36][ERRO R] Thisisanerrormessage.” “[2023–03–15T14:25:36][FATA L] Thisisafatalmessage.”
注意事项:
•需要确保网络连接正常且防火墙允许指定端口通信。
•实际生产环境中应考虑添加错误处理机制、日志缓冲队列等优化措施。
•本示例仅用于演示基本原理,请根据实际需求进行扩展完善。
内容由零声教学AI助手提供,问题来源于学员提问