用alarm()为recvfrom设置定时器

转载自:https://www.cnblogs.com/dreamrun/p/4047795.html

  因为项目需要,需要以5s为周期,收集广播信息,所以就要用到定时器和recvfrom函数,而在实用的过程中发现,5s到了,而程序仍然处于阻塞状态,一直纠结了好久,才找到问题所在,在此mark一下,以备后期回顾。


  归根结底,原因在于使用的signal()函数:signal()是重启函数,超时以后会自动启动已阻塞的函数,而不是中断它的执行,如recvfrom,给人的感觉就是使用了alarm,但依然阻塞在了recvfrom上,不往下执行。但在中断处理函数中用printf函数打印一条消息,就会发现,其实它是中断过的,只是返回后又阻塞在了recvfrom上而已。
 
  而使用sigaction函数,可以设置是否要重启函数,即alarmact.sa_flags = SA_NOMASK;选项,它会中断已阻塞的函数,使程序继续往下执行。而SA_RESTART选项则等同于signal效果,会重启函数,阻塞在recvfrom上。

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>

int n;
char recvbuf[1024];

void listen_board();

static void dealSigAlarm(int sigo)
{
    n = -1;
    printf("alarm interrupt!\n");
    return;//just interrupt the recvfrom()
}

void main()
{

    struct sigaction alarmact;


//  signal(SIGALRM,dealSigAlarm);

    bzero(&alarmact,sizeof(alarmact));
    alarmact.sa_handler = dealSigAlarm;
//  alarmact.sa_flags = SA_RESTART;
    alarmact.sa_flags = SA_NOMASK;

    sigaction(SIGALRM,&alarmact,NULL);

    listen_board();

}
void listen_board()
{
    int sock;
    struct sockaddr_in fromaddr;
    int len = sizeof(struct sockaddr_in);

    bzero(&fromaddr,len);
    fromaddr.sin_family = AF_INET;
    fromaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    fromaddr.sin_port = htons(9000);

    if((sock = socket(AF_INET,SOCK_DGRAM,0)) == -1 )
    {
        perror("socket create error.\n");
    }

    
    while(1)
    {
        alarm(5);
        n = recvfrom(sock,recvbuf,1024,0,(struct sockaddr *)&fromaddr,&len);
        if(n < 0)
        {
            if(errno == EINTR)
                printf("recvfrom timeout.\n");
            else
                printf("recvfrom error.\n");
        }
        else
            alarm(0);
    }
}

 

按照上述程序运行,得到的结果如下图所示(既调用了中断函数,又终止了recvfrom函数):

而设置为alarmact.sa_flags = SA_RESTART;选项时,结果如下图(仅调用了中断函数,却阻塞在了recvfrom上,结果与使用signal()函数效果相同):

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值