Chinaunix

标题: 求助: alarm第二次不能起作用和UDP问题 [打印本页]

作者: call_center    时间: 2005-12-19 13:14
标题: 求助: alarm第二次不能起作用和UDP问题
在REDHAT 9编程中遇到两个问题,已经被折磨了好几天了,希望有高手可以指点一二,谢谢先

问题一:
通过UDP连接发送报文的函数, 在对方机器不存在的情况下, 用SEND函数发送报文会返回ERRNO为29的错误,即连接拒绝,但有时候又成功, 所以无法根据这点来判断对方程序是否正常, 是什么原因? 大家有遇到类似的问题吗?


问题二:
有一个简单的函数, 接收已建立UDP连接的SOCKET上来的数据, 需要循环调用

如果超时没有收到数据,返回一个值, 调用处做了一些处理后循环调用该函数



我目前遇到的问题是, 如果接收不到数据,第一次超时的时候, 都可以判断出超时, 

但之后就再也无法触发超时事件


函数如下:

jmp_buf udp_jmp_env;

void handle_timeout()
{
        printf("\nTime Out.\n");

        alarm ( 0 );       
        signal ( SIGALRM , handle_timeout );       
        longjmp ( udp_jmp_env , 1 );
}

int RecvData(int iTimeout, struct commhb *rcv_hb)

{

         char sBuffer[512];

         int  iRcvLen;

         int  iRet;

         

         iRet = 0;

         alarm(iTimeout);

         signal ( SIGALRM , handle_timeout );        

         if ( setjmp ( udp_jmp_env ) != 0 )

         {

                   iRet = alarm(0);

                   printf("Into setjmp.\n");

                   return(1);



         }

         memset(sBuffer, 0, sizeof(sBuffer) );

         if ((iRcvLen=recv(server_fd, sBuffer, MAXDATASIZE, 0)) == -1)

         {

                   perror("recv error");

                   printf("errno=%d [%s]\n", errno, strerror(errno));

                   return(2);

         }

         memcpy( (char *)rcv_hb, sBuffer+2, sizeof(struct commhb) );

         alarm(0);

         return(0);

}  


其中,下面这两句的顺序调整过,结果一样
         alarm(iTimeout);
         signal ( SIGALRM , handle_timeout );
作者: batchmain    时间: 2005-12-19 13:46
你是如何调用RecvData()函数的,请说明一下
作者: call_center    时间: 2005-12-19 15:02
调用的地方比较简单:

  while(1)
  {
          memset(&rcv_hb, 0, sizeof(rcv_hb) );
          iRet = RecvData(gl_iTimeOut, &rcv_hb);
          if ( iRet == 0 )
          {
                  //Display receive data
          }
          else
          {
                //Error process
          }


  }
作者: lw371    时间: 2005-12-19 15:37
char sBuffer[512];
估计是sBuffer溢出了,导致栈上的iTimeOut<=0
在alarm(iTimeout)前printf("%d\n",iTimeout)看看
还有你的MAXDATASIZE定义的是否超过了512
作者: call_center    时间: 2005-12-19 16:23
原帖由 lw371 于 2005-12-19 15:37 发表
char sBuffer[512];
估计是sBuffer溢出了,导致栈上的iTimeOut<=0
在alarm(iTimeout)前printf("%d\n",iTimeout)看看
还有你的MAXDATASIZE定义的是否超过了512


MAXDATASIZE定义的刚好是512, 通讯报文的实际数据量大概100字节不到。
跟踪过iTimeout的值, 值正常。


其实我怀疑问题是出在跳转上, 如果不用调转, 每次超时PRINTF一条信息,倒是很正常

但是程序流程中,必须要跳转调用recv的前一个语句,从这里返回错误信息才有意义。
作者: call_center    时间: 2005-12-19 16:40
标题: 谢谢大家,问题已经解决
用sigsetjmp, siglongjmp替换了原来setjmp和longjmp, 就可以解决这个问题了。
作者: CNL    时间: 2005-12-19 16:46
应该用sigsetjmp和siglongjmp函数代替setjmp和longjmp,
longjmp从超时事件处理函数handle_timeout中直接跳出没有清除signal的mask,
这样将导致以后的超时SIGALRM不会被置位当然就不可能再触发执行超时事件函数,
而sigsetjmp和siglongjmp可以将signal block mask恢复到sigsetjmp时的状态

  1.   if ( sigsetjmp( udp_jmp_env, 1 ) != 0 )  // savemask=1: not zero to saved signal mask
复制代码

  1. void handle_timeout()
  2. {
  3.         printf("\nTime Out.\n");
  4.         siglongjmp( udp_jmp_env, 1 );
  5. }

复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2