使用alarm控制阻塞connect()超时的示例

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

static void catchup()
{
printf("alarm timeout ");
}

int alarm_connect(const char *dstip, int port, int timeout)
{
int sockfd = 0;
int oldtime = 0, old_remtime = 0, cur_remtime = 0;
struct sockaddr_in s;
struct sigaction act,oact;

act.sa_handler = catchup;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_flags |= SA_INTERRUPT; //设置收到信号后中断,不自动重启connect系统调用;若act.sa_flags |= SA_RESTART则系统调用被中断后会自动重启,达不到中断阻塞态connect的效果

printf("dst:%s, port:%d, timeout:%d ", dstip, port, timeout);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("LINE:%d, create socket fail ", __LINE__);
return -1;
}

if ((s.sin_addr.s_addr = inet_addr(dstip)) == 0xffffff)
{
printf("LINE:%d, inet_addr fail ", __LINE__);
close(sockfd);
return -1;
}

s.sin_family = AF_INET;
s.sin_port = htons(port);

sigaction(SIGALRM, &act, &oact); //设置SIGALRM处理动作
oldtime = alarm(timeout);//时钟到时产生信号,会打断阻塞态的connect()函数
if (connect(sockfd, (struct sockaddr *)&s, sizeof(s)) < 0)
{
int e;
e = errno;
cur_remtime = alarm(0);//清除alarm
sigaction(SIGALRM, &oact, &act);//恢复SIGALRM处理动作
old_remtime = oldtime - (timeout - cur_remtime);
if(old_remtime <= 0)
old_remtime = 1;

if(oldtime )
  alarm(old_remtime);
if(e == EINTR)
{
/*connect被信号打断*/
printf("LINE:%d, connect timeout ", __LINE__);
}
else
{
printf("LINE:%d, connect error ", __LINE__);
}
close(sockfd);
return -1;
}
cur_remtime = alarm(0);//清除alarm
sigaction(SIGALRM, &oact, &act);//恢复SIGALRM处理动作
old_remtime = oldtime - (timeout - cur_remtime);
if(old_remtime <= 0)
old_remtime = 1;

if(oldtime )
  alarm(old_remtime);

close(sockfd);
return 0;
}

int main(int argc, char** argv)
{
int i=0;

if(argc < 4 )
{
printf("usag:test <dstip> <port> <timeout> ");
return -1;
}
for(i=0; i<4; i++)
{
if(alarm_connect(argv[1], atoi(argv[2]), atoi(argv[3])) != 0)
{
printf("============================================ ");
printf("LINE:%d, trytimes:%d ", __LINE__, i);
printf("============================================ ");
continue;
}
else
{
printf("++++++++++++++++++++++++++++++++++++++++++ ");
printf("connect sucess, trytimes:%d ", i);
printf("++++++++++++++++++++++++++++++++++++++++++ ");
break;
}
}

return 0;
}

原文地址:https://www.cnblogs.com/wangliangblog/p/13262848.html