主流的服务器都标配一个日志文件,其文件用于记录服务器运行的日常信息,例如某个时间段的用户请求连接数、访问文件统计数、成功或完成请求连接数、服务器出错信息等等、该文件主要帮助服务器管理员更好地了解服务器的运行情况。
具体操作函数实现:
(1)打开日志文件:
int log_file_open(const char *pathname)
{
int fd = 0;
fd = open(pathname, O_WRONLY|O_APPEND|O_CREAT);
return fd;
}
(2)往日志文件中写入信息:
int log_file_writen(char *logfile,char *filename, int *line, const char *fmt, ...)
{
/* open the log_file and init it */
const char *pathname;
int fd;
char *path = logfile;
fd = log_file_open(path);
if(fd == -1)
{
return -1;
}
va_list ap;
time_t timep;
char *time_string = calloc(1,256), *ptr = calloc(1,1024);
char *buf1;
buf1 = calloc(1, 64);
int len = 0;
time(&timep);//取得当地时间
struct tm *timeinfo;
timeinfo = localtime(&timep);
strftime(time_string, 256, "%Y年%m月%d日 %H时%M分%S秒", timeinfo); //创建字符串时间戳
string_append(ptr, strlen(ptr), time_string, strlen(time_string));
string_append(ptr, strlen(ptr), "(", strlen("("));
string_append(ptr, strlen(ptr), filename, strlen(filename));
string_append(ptr, strlen(ptr), ":", strlen(":"));
int_to_string(buf1, line);
string_append(ptr, strlen(ptr), buf1, strlen(buf1));
len = string_append(ptr, strlen(ptr), ")", strlen(")"));
for(va_start(ap, fmt); *fmt; fmt++)
{
int d;
char *s;
char *buf;
buf = calloc(1, 64);
//off_t o;
switch(*fmt)
{
/* string */
case 's':
case 'S':
s = va_arg(ap, char *);
string_append(ptr, strlen(ptr), " ", strlen(" "));
string_append(ptr, strlen(ptr), s, strlen(s));
break;
/* int(digital) */
case 'd':
case 'D':
d = va_arg(ap, int);
int_to_string(buf, d);
string_append(ptr, strlen(ptr), " ", strlen(" "));
string_append(ptr, strlen(ptr), buf, strlen(buf));
break;
case '(':
case ')':
case '<':
case '>':
case ',':
case ' ':
*buf = *fmt;
string_append(ptr, strlen(ptr), buf, strlen(buf));
break;
}
va_end(ap);
}
*(ptr + strlen(ptr)) = '\r';
*(ptr + strlen(ptr) + 1) = '\n';
*(ptr + strlen(ptr) + 2) = '\0';
writen(fd, ptr,strlen(ptr));
free(ptr);
free(time_string);
close(fd);
return 0;
}
下面是(2)中调用到的操作函数实现:
//将整型转换为字符
int int_to_string(char *buf, int val)
{
char swap;
char *fin;
int temp = val;
if(temp < 0)
{
*(buf++) = '-';
temp = -temp;
}
fin = buf;
while(temp > 9)
{
*fin = 48 + (temp % 10);
fin++;
temp = temp / 10;
}
*(fin) = 48 + temp;
*(fin + 1) = '\0';
while(buf < fin)
{
swap = *fin;
*fin = *buf;
*buf = swap;
buf++;
fin--;
}
return 0;
}
//往套接字描述符中写n个字节
size_t writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while(nleft > 0)
{
if((nwritten = write(fd, ptr, nleft)) <= 0)
{
if(nwritten < 0 && errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
//在字符串a的末尾添加字符串b
int string_append(char *a, size_t a_len, char *b, size_t b_len)
{
int i;
for(i = 0;i <= b_len; i++)
{
*(a + a_len + i) = *(b + i);
}
return (a_len + b_len + 2);
}
效果例子:
19时35分19秒(test.c:69) head:accept has text/html