C:写一个适当的超时



仔细浏览资源后,我仍然不完全确定如何在c中编写适当且可用的计时器函数。我不使用线程(或可并行代码)。我只是想写一个秒表函数,我可以使用它在一小段时间过去后触发一段代码。

这是一个非常常见的定时器的使用,在"超时"的情况下,我有一个客户端-服务器设置,其中客户端正在发送一些数据(UDP风格与sendto(…)和recvfrom(…))。我已经编写了我的系统,以便客户端在我定义的数据包结构中发送数据块,服务器通过CRC处理它,然后发回一个确认包(ACK),表示收到了未损坏的消息。但是,我想实现一个超时,如果客户机在一段时间内没有收到ACK,客户机就会重新发送数据块(当然服务器会检查是否有重复)。我想在客户端嵌套这段计时器代码,出于某种原因,我认为这应该没有那么困难。

我从我很久以前做过的工作中挖出了旧的信号处理代码,因为这似乎是我通常看到的唯一解决方案,请问有人可以指导我如何使用以下信号处理代码,而不仅仅是接收定时信号,而是触发某种动作。从概念上讲,我觉得它应该是:"发送数据,启动计时器,计时器到期后执行重发,重置计时器……重复,直到收到ACK为止。更好的是,有一种更简单的方法来编写计时器函数,但鉴于C是一种低级语言,这看起来不太可能实现....

#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
extern char *strsignal(int sig);
void timer_handler(int a)
{
  // handle signal
  printf(">>>> signal caughtn");
  printf(">>>>    int parameter = %sn", (char*) strsignal(a));
}
int main(int argc, char* argv[])
{
  int retval;
  struct itimerval timerValue;
  struct itimerval oldTimerValue;
  struct sigaction action;
  action.sa_handler = &timer_handler;
  action.sa_flags = SA_NODEFER;
  // initialize timer parameters: expires in 5 seconds
  timerValue.it_interval.tv_sec = 5;
  timerValue.it_interval.tv_usec = 0;
  timerValue.it_value.tv_sec = 5;
  timerValue.it_value.tv_usec = 0;
  // install signal handler to catch SIGALRM
  //signal(SIGALRM, timer_handler);
  sigaction(SIGALRM, &action, NULL);
  retval = setitimer(ITIMER_REAL, &timerValue, &oldTimerValue);
  if (-1 == retval)
    perror("Could not set timer");
  while(1);
  return 0;
}

Xymostech提供了我需要的确切功能,在咨询了"select"的API(其中包括一个小的使用示例)之后,我修改了那里的代码以适合我需要的内容,并编写了一个套接字计时器(对于读取,它很容易扩展到写入等,因为"select"有启用这种检查的参数)。确保包含了以下由"select" API指定的库:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdio.h>

下面是我从API示例中创建的waittoread(…)函数,它工作得很好。这在我的特定问题的领域工作得很好,然而,如果一个人正在寻找一个更通用的定时器(即不只是定时套接字读写,或文件描述符)请咨询信号处理(有点在我在我最初的问题中发布的代码的精神)。

#define S1READY 0x01 // necessary for the function's bitwise OR operation
int waittoread(int s1, int timeout_value){
   fd_set fds; // create set of sockets to be waited on
   struct timeval timeout; // the time-out value
   int rc; // # of sockets that are ready before timer expires
   int result;
   /* Set time limit. */
   timeout.tv_sec = timeout_value;
   timeout.tv_usec = 0;
   /* Create a descriptor set containing the socket.  */
   FD_ZERO(&fds); // MACRO to reset the socket storage set so new ones can be added
   FD_SET(s1, &fds); // add the socket descriptor into the socket set to wait on
   rc = select(sizeof(fds)*4, &fds, NULL, NULL, &timeout); // build the socket-wait system
   // another way of calling select that would be a better approach:
   // rc = select(s1 + 1), &fds, NULL, NULL, &timeout);
   if (rc==-1) {
      perror("Error:  Call to select failed.");
      return -1;
   }
   result = 0;
   if (rc > 0){
      if (FD_ISSET(s1, &fds)) result |= S1READY;  // if the result is non-zero, perform a BIT-wise OR to extract the true socket count #
   }
   return result;
}

相关内容

  • 没有找到相关文章

最新更新