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/

  • 相关阅读:
    Unity 3(一):简介与示例
    MongoDB以Windows Service运行
    动态SQL中变量赋值
    网站发布IIS后堆栈追踪无法获取出错的行号
    GridView Postback后出错Operation is not valid due to the current state of the object.
    Visual Studio 2010 SP1 在线安装后,找到缓存在本地的临时文件以便下次离线安装
    SQL Server 问题之 排序规则(collation)冲突
    IIS 问题集锦
    linux下安装mysql(ubuntu0.16.04.1)
    apt-get update 系列作用
  • 原文地址:https://www.cnblogs.com/eleclsc/p/12306254.html
Copyright © 2011-2022 走看看