从一组套接字中检测超时套接字

Detecting a timed out socket from a set of sockets

本文关键字:套接字 检测 超时 一组      更新时间:2023-10-16

我目前正在使用winsock构建服务器。我的服务器将处理多个客户端,所以我使用select()函数和读、写和异常集。我已经知道,如果特定的套接字超时,select()返回0。

但是我如何识别超时的实际套接字?

BTW,谁能告诉我什么需要发生在Some_Socket的FD_ISSET(Some_Socket, &Exception)返回真?

也许我可以使用上面的函数检查集合中的每个套接字?

编辑:

假设我有这样一个例子:

int main(void){
       fd_set rfds;
       struct timeval tv;
       int retval;
       /* Watch stdin (fd 0) to see when it has input. */
       FD_ZERO(&rfds);
       for(int i = 0; i<clientcount; i++) {

        FD_SET(sockets[i].Scksas, &read_mask);
        FD_SET(sockets[i].Scksas, &write_mask);
        FD_SET(sockets[i].Scksas, &excep_mask);
   }
       /* Wait up to five seconds. */
       tv.tv_sec = 5;
       tv.tv_usec = 0;
       retval = select(1, &rfds, NULL, NULL, &tv);
       /* Don't rely on the value of tv now! */
       if (retval == -1)
           perror("select()");
       else if (retval)
           printf("Data is available now.n");
           /* FD_ISSET(0, &rfds) will be true. */
       else{
           printf("No data within five seconds.n");
           /*
             Handle timed out socket, but which one ?
           */
       }
       exit(EXIT_SUCCESS);
   }

我该如何确定哪个套接字超时?

问题是你不能使用select等,因为他们的超时是针对整个套接字集而不是单个套接字。

有三种简单的解决方案可以找出在特定时间段内没有通信的单个套接字。

  1. 最简单的可能是为每个套接字保持一个结构,并在这个结构中有最后一次通信的时间。每隔一段时间检查所有套接字的时间,如果时间太长,则关闭连接。

  2. 另一个解决方案是在协议中有一个"keep alive"消息。定期在所有套接字上发送"你还活着吗"消息。

  3. 如果您在超时时间内没有收到"我还活着"的回复,则可以认为连接已失效,您可以关闭它。
  4. 为每个套接字使用单独的线程或进程。然后您可以使用select,因为您在集合中只有一个套接字。

更具体地说,如果在指定的超时时间内没有选择套接字,select()返回0。如果返回值为正数,则表示所设置的套接字数量(负返回值为选择错误)。知道设置了哪个套接字以及在哪里设置的正确方法是在每个套接字、每个集合上使用FD_ISSET,例如

if ( 0 != FD_ISSET( sock, &efds ) )...

我已经知道,如果一个特定的套接字超时,select()返回0。

不,你没有。如果所有套接字超时,则返回零。在这种情况下,很容易:关闭它们。

如果返回非零,则必须处理读/写FD集合中的所有FD;那么就可以处理这些集合中不是的所有fd。您需要维护所有fd的最后I/O时间,并在该循环中检查是否有超过超时限制的。