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

时间:2013-01-17 12:18:44

标签: c++ windows sockets timeout winsock

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

但是我如何确定超时的实际套接字?

BTW,有谁能告诉我,对于FD_ISSET(Some_Socket,& Exception),Some_Socket需要发生什么才能返回true?

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

编辑:

我们说我有这个例子:

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);
   }

我该如何确定哪个soket超时?

3 个答案:

答案 0 :(得分:2)

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

有三种简单的解决方案可以找出在一段时间内没有通信的个人插座。

  1. 最简单的可能是为每个套接字保留一个结构,并且在此结构中有最后一次通信的时间。您可以定期检查所有插座的时间,如果时间很久,则关闭连接。

  2. 另一种解决方案是在协议中包含“保持活动”消息。定期发送所有套接字上的“你还活着”消息。如果你在一段时间内没有收到“我还活着”的回复,那么连接可能会被认为是陈旧的,你可以关闭它。

  3. 为每个套接字使用单独的线程或进程。然后你可以使用select,因为你在集合中只有一个套接字。

答案 1 :(得分:1)

更具体地说,如果在指定的超时时间内选择了NONE,则select()返回0。如果返回是正数,则它是设置的套接字数(负返回是选择错误)。知道哪个套接字设置和在哪里的正确方法是在每个套接字上使用FD_ISSET,例如。

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

答案 2 :(得分:0)

  

我已经知道如果特定套接字超时,select()将返回0.

不,不。如果 all 套接字超时,则返回零。在这种情况下,这很简单:关闭它们。

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