设置套接字超时不起作用。

8 浏览
0 Comments

设置套接字超时不起作用。

我正在使用setsockopt()函数来设置recvfrom()函数的超时时间。由于我使用的协议的特殊性,我需要先设置2秒的超时时间,然后是4秒、6秒,直到达到最大值。但是当我使用这个函数时,似乎超时时间只有0.01秒,因为它发送了8个数据包而没有等待。

//更多变量和代码
struct timeval timeout = {2, 0};
while(1){
  setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(struct timeval));
  temp2 = recvfrom(sock, &buff, sizeof(buff), 0, (struct sockaddr *)&addr_server, sizeof(addr_server));
  if(temp2 < 0){ /* 超时 */
      temp = sendto(sock, (struct udp_PDU*)®_pdu, sizeof(reg_pdu), 0, (struct sockaddr *)&addr_server, sizeof(addr_server));
      if(temp == -1){
        printf("发送失败\n");
        exit(-1);
      }
      packet_counter++;
      debug("发送注册请求包");
      if(packet_counter == 8) break;
      if((interval * max) > t ) timeout.tv_sec+=interval;
  }else{ /* 接收到数据 */
    correct = 1;
    break;
  }
}

0
0 Comments

设置套接字的超时时间不起作用的原因是超时不是延迟语句,而是一种防止recv()recvfrom()等调用无限期阻塞的方法。如果数据传输在超时设置之前出现,那就更好了。函数接收到数据后,程序流程继续执行。超时设置为2秒,如果没有任何操作发生,它会停止等待,使程序继续执行,即不再阻塞。没有超时,recv()recvfrom()等函数可能会永远阻塞。

如果你想在recvfrom()sendto()调用之间强制使用2秒间隔(或阻塞),请在循环中的某个位置添加sleep(2);(在Windows上使用Sleep(2000);)。可能是在底部。

while(1){
    ...
    }
    sleep(2);  //or on Windows, Sleep(2000);
}

顺便说一下,习惯性地检查任何具有返回值的函数的返回值是一个好习惯,特别是如果该函数的失败会对代码的其余部分产生严重影响。例如:

if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(struct timeval)) < 0) {
    perror("Error");
}
...

与此相关的几个话题:

  • 这篇帖子中描述了更精确的sleep间隔控制选项。
  • 在这些帖子中讨论了使用poll()的结构:Sockets using poll()select() with sockets(第二个更倾向于使用poll())。
  • 在这个SO问题中讨论了使用select()函数。
0