1

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

但是我怎样才能识别超时的实际套接字呢?

顺便说一句,谁能告诉我 Some_Socket 需要发生什么才能使 FD_ISSET(Some_Socket, &Exception) 返回 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 超时?

4

3 回答 3

2

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

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

  1. 最简单的大概就是为每个socket保留一个结构,并且在这个结构中有个最后一次通信的时间。定期检查所有套接字的这个时间,如果时间太早,则关闭连接。

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

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

于 2013-01-17T12:20:11.600 回答
1

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

if ( 0 != FD_ISSET( sock, &efds ) )...
于 2013-01-17T13:25:06.093 回答
0

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

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

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

于 2013-01-17T18:12:16.373 回答