前言
此博客记录对于TinyWebServer项目的学习,并根据自己的理解做出些许更改。
原项目地址:https://github.com/qinguoyi/TinyWebServer
定时器
网络程序通常需要处理定时事件,例如定期检测客户连接的活动状态,因为非活跃连接占用了连接资源,需要定期检测释放非活跃连接。通常将定时事件封装为定时器类,然后使用排序链表、时间轮等数据结构管理定时器。
linux提供了三种定时方法,
1.socket选项SO_RCVTIMEO和SO_SNDTIMEO
2.SIGALRM信号
3.I/O复用系统调用的超时参数。
这里使用的是SIGALRM信号。
SIGALRM信号
SIGALRM信号是是设置进程隔多久后会收到一个SIGALRM信号,alarm()是设置多久触发SIGALRM信号的函数。
例如alarm(2),即是2秒后给当前进程发SIGALRM信号,触发SIGALRM绑定的函数。
例如
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void sig_handler(int num)
{
printf("signal = %d\n", num);
alarm(2);
}
int main()
{
signal(SIGALRM, sig_handler);
alarm(2);
int num = 0;
while(1)
{
sleep(1);
printf("计时:%d\n", ++num);
}
return 0;
}
运行结果,注意SIGALR信号被定义为(int)14
升序链表实现定时器
定时器类的封装
//前向声明
class util_timer;
//连接资源
struct client_data
{
sockaddr_in address; //连接地址
int sockfd;
util_timer *timer; //指向连接对应的定时器
};
//定时器类:以一个双向链表实现
class util_timer
{
public:
util_timer() : prev(NULL), next(NULL) {}
public:
//超时时间
time_t expire;
//回调函数:从内核事件表删除事件,关闭文件描述符,释放连接资源
//定义函数指针,使用时指向要使用的函数
void (* cb_func)(client_data *);
//连接资源
client_data *user_data;
//前向定时器
util_timer *prev;
//后继定时器
util_