【C++实现HTTP服务器项目记录】定时器处理非活动连接

一、非活跃连接

- 非活跃连接:客户端(浏览器)与服务器端建立连接后,长时间不交换数据,一直占用服务器端资源。
- 针对非活跃连接,需要在内核事件表删除对应事件、关闭文件描述符、释放连接资源等。

二、信号

- Linux中的信号是一种消息处理机制,它本质上是一个整数,不同的信号对应不同的值,信号在系统中的优先级是非常高的。
- 项目中使用的信号
 	1. SIGALRM:定时器超时信号,超时的时间由系统调用alarm设置,默认终止进程。
 	2. SIGTERM:程序结束信号,kill或Ctrl+C触发,默认终止进程。
- 两个特殊信号
	1. SIGKILL:9号信号,无条件终止进程,不能被捕捉、阻塞和忽略。
	2. SIGSTOP:19号信号,无条件暂停进程,不能被捕捉、阻塞和忽略。

三、信号捕捉

- Linux中的每个信号产生之后都会有对应的默认处理行为,如果想要忽略某些信号或者修改某些信号的默认行为就需要在程序中捕捉该信号。
- 程序中的信号捕捉是一个注册的动作,提前告诉应用程序信号产生之后的处理动作,当进程中对应的信号产生了,这个处理动作也就被调用了。
struct sigaction
{
   
    void (*sa_handler)(int);                        // 函数指针,指向信号处理函数。
    void (*sa_sigaction)(int, siginfo_t *, void *); // 函数指针,指向信号处理函数。
    sigset_t sa_mask;                               // 在信号处理函数执行期间,临时屏蔽的信号。
    int sa_flags;                                   // SA_RESTART:使被信号打断的系统调用自动重新发起。
                                                    // SA_SIGINFO:使用第二个函数指针。
    void (*sa_restorer)(void);                      // 被废弃的成员。
};

int sigaction(
    int signum,                  // 要捕捉的信号。
    const struct sigaction *act, // 信号的处理动作。
    struct sigaction *oldact     // 上一次信号处理动作,一般指定为NULL。
);

四、定时器

// 倒计时seconds秒,倒计时完成发送SIGALRM信号,当前进程会收到这个信号。
unsigned int alarm(unsigned int seconds);

五、统一事件源

- 1. 一般的信号处理函数需要处理该信号对应的逻辑,当该逻辑比较复杂时,信号处理函数执行时间过长,会导致信号屏蔽太久。
- 解决方法:
	信号处理函数仅发送信号的值,通知程序主循环,程序主循环中执行信号对应的逻辑代码。
	
- 2. 统一事件源:将信号事件与其他事件一样被处理。
- 解决方法:
	信号处理函数往管道的写端写入信号值,主循环则从管道的读端读出信号值。
	使用I/O复用系统调用监听管道读端的可读事件与其他文件描述符,从而实现统一处理。

六、实现代码

1. lst_timer.h

/*
 * 带头尾结点的升序双向链表管理定时器。
 * 为每个连接创建一个定时器,将其添加到链表中,并按照超时时间升序排列。
 * 执行定时任务时,将到期的定时器从链表中删除。
 * 添加定时器的事件复杂度是O(n), 删除定时器的事件复杂度是O(1)。
 */
#ifndef LST_TIMER
#define LST_TIMER

#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/uio.h>

#include <time.h>
#include "../log/log.h"

// 连接资源结构体成员需要用到定时器类
// 需要前向声明
class util_timer;

// 连接资源结构体
struct client_data
{
   
    // 客户端Socket地址
    sockaddr_in address;
    // Socket文件描述符
    int sockfd;
    // 定时器
    util_timer *timer;
};

// 定时器类
class util_timer
{
   
public:
    // 构造函数
    util_timer() : prev(NULL),<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值