• 非活跃,是指客户端(这里是浏览器)与服务器端建立连接后,长时间不交换数据,一直占用服务器端的文件描述符,导致连接资源的浪费。

  • 定时事件,是指固定一段时间之后触发某段代码,由该段代码处理一个事件,如从内核事件表删除事件,并关闭文件描述符,释放连接资源。

  • 定时器,是指利用结构体或其他形式,将多种定时事件进行封装起来。具体的,这里只涉及一种定时事件,即定期检测非活跃连接,这里将该定时事件与连接资源封装为一个结构体定时器。

  • 定时器容器,是指使用某种容器类数据结构,将上述多个定时器组合起来,便于对定时事件统一管理。具体的,项目中使用升序链表将所有定时器串联组织起来。


Linux下提供了三种定时的方法:

  • socket选项SO_RECVTIMEO和SO_SNDTIMEO
  • SIGALRM信号
  • I/O复用系统调用的超时参数

Socket选项

img

struct timeval timeout;
timeout.tv_sec = time;
timeout.tv_usec = 0;

socklen_t time_len = sizeof(timeout);
ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, time_len); //发送数据超时
用返回值errno判断是否达到指定时间 (errno == SO_SNDTIMEO)

SIGALRM信号

sigaction结构体

struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
}

sa_handler是一个函数指针,指向信号处理函数 sa_sigaction同样是信号处理函数,有三个参数,可以获得关于信号更详细的信息 sa_mask用来指定在信号处理函数执行期间需要被屏蔽的信号 sa_flags用于指定信号处理的行为 SA_RESTART,使被信号打断的系统调用自动重新发起 SA_NOCLDSTOP,使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号 SA_NOCLDWAIT,使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程 SA_NODEFER,使对信号的屏蔽无效,即在信号处理函数执行期间仍能发出这个信号 SA_RESETHAND,信号处理之后重新设置为默认的处理方式 SA_SIGINFO,使用 sa_sigaction 成员而不是 sa_handler 作为信号处理函数 sa_restorer一般不使用

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

Re:

定时器-Web服务器项目