当前位置:   article > 正文

Linux-定时器_linux timer_connect

linux timer_connect


定时是指一段时间后触发某段代码的机制,Linux提供了以下三种定时方法:

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

socket选项SO_RCVTIMEO和SO_SNDTIMEO

分别用来设置socket接收数据超时时间和发送数据超时时间,所以用于与socket数据收发有关的系统调用,如send,recv,sendmsg,recvmsg,accept,connect等。
在这里插入图片描述

example,connect超时

int timeout_connect(const char* ip, int port, int time{
	/* 
	初始化socket参数
	*/
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	struct timeval timeout;
	timeout.tv_sec = time;
	timeout.tv_usec = 0;
	socklen_t len = sizeof(timeout);
	ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, len);
	assert(ret != -1);
	ret = connect(sockfd, (sockaddr*)&addr, sizeof(addr));
	if(ret == -1){
		
		if(errno == EINPROGRESS){
			// connect系统调用超时了,处理定时任务
			return -1;
		}
		// 连接到server时的错误
		return -1;
	}
}

int main(){
	int sockfd = timeout_connect(ip, port, time);
	if(sockfd < 0){
		return -1;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

SIGALRM

alarm和settimer函数设置的实时闹钟一旦超时,就会触发SIGALRM信号。

基于升序链表的定时器

定时器通常包含超时时间和任务回调函数。有时还含有回调函数的参数和是否重启定时器的信息。
原文中使用了双向链表,但没有使用头尾节点,编程实现繁琐,这里给出带头尾节点的实现方法:
Cpp实现

处理非活动连接

服务器通常需要定期处理非活动连接,给客户端发送重连请求或关闭连接。
Linux内核中提供了socket的KEEPALIVE选项来定期检查连接是否处于活动状态的定期检查机制。
但是这种机制使得应用程序对于连接的管理变得复杂,我们可以在应用层来实现类似的机制。

一下代码利用alarm函数周期性触发SIGALRM信号,该信号的信号处理函数利用管道通知主循环执行定时器链表上的定时任务——关闭非活动的连接。
代码实现链接

IO复用系统调用的超时参数

因为I/O复用可能在超时时间到期之前就返回(有就绪事件发生),所以如果需要使用I/O复用的超时的话,需要不断更新定时参数以反映剩余时间。

const int TIMEOUT = 5000;
int timeout = TIMEOUT;
time_t start = time(NULL);
time_t end = time(NULL);

while(true){
	printf("The timeout is now %d mil-seconds\n", timeout);
	start = time(NULL);
	int number = epoll_wait(epollfd, events, MAX_NUM, timeout);
	if(number < 0){
		// error
		break;
	}
	else if(number == 0){
		// 说明epoll_wait超时时间到了,此时可处理定时任务,并重置定时时间
		timeout = TIMEOUT;
		continue;
	}
	end = time(NULL);
	// 如果epoll_wait的返回值大于0,则本次调用的持续时间是
	// (end - start) * 1000 ms, 我们需要处理一下
	timeout = timeout - (end - start) * 1000;
	if(timeout <= 0){
		timeout = TIMEOUT;
	}
	// handle connections;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

高性能定时器

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/225188
推荐阅读
相关标签
  

闽ICP备14008679号