使用Select时读取时超时

时间:2013-10-18 17:29:46

标签: c sockets network-programming

这是我的情况,我正在使用UDP,并且有一个服务器正在向我发送数据,但由于数据包丢失,他也可能无法发送数据,我希望他重新发送,但是我的客户也可能没有收到数据,所以我希望他重读一遍。现在,我决定在我的客户端上超时,他将等待一段时间,然后重新阅读。我的问题是,只是添加一个转到选择的goto来解决问题,或者在第一次超时后选择被打破?我是否必须使套接字无阻塞?我在网上的某处读到了。基本上,我的目标是,如果没有发生读取,请在一段时间后再试一次,因为我知道发件人正在尝试发送。我想知道我的逻辑是否正确,因为我无法测试它。

  fd_set set;
  struct timeval timeout;
  int rv;
  char buff[100];
  int len = 100;

  FD_ZERO(&set); /* clear the set */
  FD_SET(sockfd, &set); /* add our file descriptor to the set */

  timeout.tv_sec = 0;
  timeout.tv_usec = 10000;

  retry:
  write(sockfd,"hi",3);//sent to client now waiting for an ack
  rv = select(sockfd + 1, &set, NULL, NULL, &timeout);
  read(sockfd, buff, strlen(buff), 0);
  if(rv == -1)
    perror("select"); /* an error accured */
  else if(rv == 0)
    printf("timeout");
    goto retry;
  else
    read( filedesc, buff, len ); /* there was data to read */
}

1 个答案:

答案 0 :(得分:1)

我会怀疑select会修改你的fd_set,以便它在读取后不再包含你的sockfd(因为它还没有准备好读取)。所以只是为了确保在重试之前重新初始化集合。或者您可以尝试在超时后fd仍然存在,但我认为正常的行为是在调用select之前重新初始化所有FD。 如果您使用民意调查或epoll,则不必这样做。

除此之外,代码看起来还不错。

无论您使用blockin还是非阻塞IO,对您的案例中的读取都无关紧要。如果你使用非阻塞,你的写入可能会失败,因此保持阻塞更容易。