三种socket超时方法

概述

socket超时有三种处理办法:

  1. 使用alarm定时器,设置一定的超时时间,通过产生SIGALRM中断信号实现socket的超时中断。
  2. 利用select函数的超时功能,阻塞在select的调用上代替阻塞在read或write函数上
  3. 使用SO_RCVTIMEOSO_SNDTIMEO的socket选项

通过alarm定时器实现

  1. alarm的超时时间不能大于connect自身的超时时间
  2. 多线程场景很难处理
#include <unp.h>
static void connect_alarm(int);
int 
connect_timeo(int sockfd, const sockaddr *saptr, socklen_t salen, int nsec)
{
	sigfunc *sigfunc;//原始信号处理函数地址
	int n;

	sigfunc = signal(SIGALRM, connect_alarm);
	if (alarm(nsec) != 0) {//返回值大于0表示:alarm已经设置过了,返回剩余时间
		err_msg("connect_timeo: alarm war already set");
	}

	if ((n = connect(sockfd, saptr, salen)) < 0) {//中断来了,connect会立即返回,同时errno设置成EINTR
		close(sockfd);
		if (errno == EINTR) {
			errno = ETIMEDOUT;
		}
	}

	alarm(0);//恢复alarm
	signal(SIGALRM, sigfunc);//恢复signal

	return(n);
}

static void 
connect_alarm(int signo)
{
	return;
}

通过select实现

#include "unp.h"

int
readable_timeo(int fd, int sec)
{
	fd_set rset;
	struct timeval tv;

	FD_ZERO(&rset);
	FD_SET(fd, &rset);

	tv.tv_sec = sec;
	tv.tv_usec = 0;

	return(select(fd + 1, &rset, NULL, NULL, &tv));
}

出错时返回-1,超时时返回0,否则返回正数,表示已经就绪的描述符数目。

通过SO_RCVTIMEO和SO_SNDTIMEO实现

struct timeval tv;
int sockfd;
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

选项SO_RCVTIMEOSO_SNDTIMEO传参为struct timeval类型的参数,分别用于设置接收和发送的函数的超时时间。

  • 影响的接收函数:write, writev, send, sendto, sendmsg
  • 影响的发送函数:read, readv, recv, recvfrom, recvmsg

超时时,errno被设置为EAGAIN或EWOULDBLOCK。仅对阻塞模式的socket有效,非阻塞模式的socket调用上面的函数还是立即返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值