免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2004 | 回复: 6
打印 上一主题 下一主题

[SCO UNIX] 求助: alarm第二次不能起作用和UDP问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-12-19 13:14 |只看该作者 |倒序浏览
在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 );

论坛徽章:
0
2 [报告]
发表于 2005-12-19 13:46 |只看该作者
你是如何调用RecvData()函数的,请说明一下

论坛徽章:
0
3 [报告]
发表于 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
          }


  }

论坛徽章:
0
4 [报告]
发表于 2005-12-19 15:37 |只看该作者
char sBuffer[512];
估计是sBuffer溢出了,导致栈上的iTimeOut<=0
在alarm(iTimeout)前printf("%d\n",iTimeout)看看
还有你的MAXDATASIZE定义的是否超过了512

论坛徽章:
0
5 [报告]
发表于 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的前一个语句,从这里返回错误信息才有意义。

论坛徽章:
0
6 [报告]
发表于 2005-12-19 16:40 |只看该作者

谢谢大家,问题已经解决

用sigsetjmp, siglongjmp替换了原来setjmp和longjmp, 就可以解决这个问题了。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
7 [报告]
发表于 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. }

复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP