zoukankan      html  css  js  c++  java
  • 【转】用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!
    ");
        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.
    ");
        }
    
        
        while(1)
        {
            alarm(5);
            n = recvfrom(sock,recvbuf,1024,0,(struct sockaddr *)&fromaddr,&len);
            if(n < 0)
            {
                if(errno == EINTR)
                    printf("recvfrom timeout.
    ");
                else
                    printf("recvfrom error.
    ");
            }
            else
                alarm(0);
        }
    }

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

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


     另:信号处理流程:若设置了信号处理函数,当信号到达时,会将控制流转向信号处理器。从信号处理器返回后,继续执行原来的控制流。

    参考资料:http://liuzhigong.blog.163.com/blog/static/178272375201172021328123/

  • 相关阅读:
    内存泄露的小问题(转载)
    脚本错误:"return 语句不能在函数之外" (转载)
    转载:asp.net网页防刷新重复提交、防后退解决办法集!
    转载:一行代码搞定你的QueryString
    转载 PowerDesigner Name/Code自动调整
    无刷新仿google波形扭曲彩色Asp.net验证码
    转载:认识Web.config文件
    转载:将数据库从SQL2000迁移到SQL2005时,无法查看关系图的解决办法
    [转]WTL的windows mobile环境的配置(vs2008)[最终版,验证通过]
    [转].NET中Cache用法分析
  • 原文地址:https://www.cnblogs.com/eleclsc/p/12306254.html
Copyright © 2011-2022 走看看