在我们的日常编程学习中,为了调试我们经常在终端上输出结果。然而,当真正为客户开发项目时,我们并没有终端来查看这些结果。因此,为了记录我们想要的结果以及程序中遇到的问题,我们需要引入日志文件的概念。
日志文件是用于记录系统操作事件的文件或文件集合,可以用于记录系统或应用程序的活动、事件及运行状态。它们提供有效的系统和应用程序状态信息,以便查询、分析和解决系统或应用程序可能出现的问题或故障。
我们使用fopen函数来创建日志文件(注意:日志文件后缀为.log)
FILE* file_log=fopen("filelog.log" ,"a");
上述代码创建了一个名为"filelog.log"的日志文件,然后我们就可以使用fprintf函数进行写入数据(fopen以及fprintf函数已经在我的C++专栏中进行了详细的介绍,感兴趣可以去看一看)
编写一个小项目:功能是监听本地的8080端口,并在有客户端连接时,将客户端的IP地址和端口号记录到日志文件中。代码如下:
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库,包含exit()函数
#include <string.h> // 引入字符串处理库
#include <unistd.h> // 引入POSIX标准库,包含fork()函数
#include <sys/socket.h> // 引入socket库
#include <netinet/in.h> // 引入网络编程的库
#include <arpa/inet.h> // 引入网络地址转换库
#define LOG_FILE "filelog.log" // 定义日志文件名
// 定义一个记录日志的函数
void log_message(const char *buff){
FILE* file_log; // 定义文件指针
file_log=fopen(LOG_FILE,"a"); // 以追加模式打开日志文件
if (file_log == NULL) { // 如果文件打开失败
perror("Failed to open log file"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序
}
fprintf(file_log,"[%d]:%s\n",getpid(),buff); // 将进程ID和消息写入日志文件
fclose(file_log); // 关闭文件
}
int main(){ // 主函数入口
char buff[1024]; // 定义缓冲区
int sock; // 定义socket变量
pid_t pid; // 定义进程ID变量
struct sockaddr_in sever_addr, client_addr; // 定义服务器和客户端的地址结构体
socklen_t client_len=sizeof(client_addr); // 定义客户端地址长度变量
sock=socket(AF_INET,SOCK_STREAM,0); // 创建socket
if(sock==-1){ // 如果socket创建失败
log_message("socket failed"); // 记录错误日志并退出程序
exit(EXIT_FAILURE); // 退出程序
}
sever_addr.sin_family=AF_INET; // 设置地址族为IPv4
sever_addr.sin_addr.s_addr=INADDR_ANY; // 设置地址为任意地址
sever_addr.sin_port=htons(8080); // 设置端口号为8080,并转换为网络字节序
bzero(&(sever_addr.sin_zero), 8); // 清零剩余的地址结构体部分(这个在现代代码中很少见,可能是为了兼容老代码)
if(bind(sock,(struct sockaddr*)&sever_addr,sizeof(sever_addr))==-1){ // 如果绑定失败
log_message("bind connect error!"); // 记录错误日志并退出程序
exit(EXIT_FAILURE); // 退出程序
}
if(listen(sock,5)==-1){ // 如果监听失败
log_message("listen error!"); // 记录错误日志并退出程序
exit(EXIT_FAILURE); // 退出程序
}
log_message("Server listening on 127.0.0.1:8080..."); // 记录服务器开始监听的日志信息
pid=fork(); // 创建子进程,父进程继续执行下面的代码,子进程执行else部分代码
if(pid==-1){ // 如果fork失败
log_message("fork error!"); // 记录错误日志并退出程序
exit(EXIT_FAILURE); // 退出程序
}
else if(pid==0){ // 子进程执行的代码块,只有当pid为0时执行此代码块,表示这是一个子进程
int client_sock; // 定义客户端socket变量
if(client_sock=accept(sock,(struct sockaddr*)& client_addr,&client_len)==-1){ // 如果接受客户端连接失败
log_message("accept error!"); // 记录错误日志,注意这里没有exit()函数,子进程会在执行完毕后自然结束
}
log_message("Client connected from 127.0.0.1:8080");
close(client_sock);
exit(EXIT_SUCCESS);
}
else{
close(sock);
log_message("Parent process continues running...");
}
return 0;
}
运行程序,打开日志文件可以看到:
成功监听!