定时器设计(一)

本文介绍了服务器定时器设计,包括基于排序链表和时间轮的实现。通过对非活跃连接的定时检查,释放连接资源。详细探讨了两种设计的结构和主要函数,如add_timer、adjust_timer和del_timer。并总结了设计中遇到的问题和不足,如时间轮设计时的数组越界问题和链表实现的优化。
摘要由CSDN通过智能技术生成


前言

客户端与服务器通过socket进行连接和通信,但是socket有限的,非活跃连接占用了连接资源,对服务器的性能影响很大,通过设计服务器定时器来处理非活跃连接,释放连接资源。


一、定时器设计

定时器的设计包括基于小根堆的定时器、基于排序链表的定时器、基于时间轮的定时器。本文主要介绍基于排序链表的定时器和基于时间轮的定时器。

定时器是将所需的定时事件封装起来,本文主要是将检测非活跃连接封装成一个定时器。

定时器回调函数:从内核事件表删除事件,关闭文件描述符,释放连接资源。

void cb_func(client_data *user_data)
{
      //删除非活动连接在socket上的注册事件
    epoll_ctl(Utils::u_epollfd, EPOLL_CTL_DEL, user_data->sockfd, 0);
    assert(user_data);
    //关闭文件描述符
    close(user_data->sockfd);
    //减少连接数
    http_conn::m_user_count--;
}

连接资源主要包括 客户端套接字地址、文件描述符、定时器。

class util_timer;

struct client_data
{
   
    sockaddr_in address;
    int sockfd;
    util_timer *timer;
};

1、基于排序链表定时器设计

基于排序链表的类包括超时时间、回调函数、连接资源、前向定时器、后继定时器。

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_timer *next;
};

2、基于时间轮定时器设计

基于时间轮的定时器类包括时间轮圈数、时间轮的槽、回调函数、连接资源、前向定时器、后继定时器。

class util_timer
{
   
public:
    util_timer(int rot ,int ts) : prev(NULL), next(NULL),rotation(rot),time_slot(ts) {
   }

public:
    // 时间轮圈数
    int rotation;
    // 时间轮的槽
    int time_slot;
    //回调函数:从内核事件表删除事件,关闭文件描述符,释放连接资源
    void (* cb_func)(client_data *);
    //连接资源
    client_data *user_data;
    //前向定时器
    util_timer *prev;
    //后继定时器
    util_timer *next;
};

二、定时器容器设计

1、基于排序链表的定时器设计

基于排序链表定时器设计,是利用alarm函数周期触发SIGALRM信号,信号处理函数通过管道通知主循环对排序链表的定时器进行处理。
定时器容器为升序双向链表,按照超时时间升序排列,根据触发信号定时将到期的定时信号从链表中删除。
升序双向链表的主要成员函数如下:

class sort_timer_lst
{
   
public:
    sort_timer_lst();
    ~sort_timer_lst();

    void add_timer(util_timer *timer);
    void adjust_timer(util_timer *timer);
    void del_timer(util_timer *timer);
    void tick();

private:
    void add_timer(util_timer *timer, util_timer *lst_head);

    util_timer *head;
    util_timer *tail;
};

1.add_timer函数,将定时器添加到链表中,如果当前链表中没有其他定时器那么直接插入链表,否则将定时器根据超时时间升序插入。

void add_timer(util_timer *timer)
{
   
   if (!timer)
   {
   
       return;
   }
   if (!head)
   {
   
       head = tail = timer;
       return;
   }
    if (timer->expire < head->expire)
   
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值