我目前正在使用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超时?
答案 0 :(得分:2)
问题在于你不能使用select
等,因为它们的超时是针对整个集合而不是单个套接字。
有三种简单的解决方案可以找出在一段时间内没有通信的个人插座。
最简单的可能是为每个套接字保留一个结构,并且在此结构中有最后一次通信的时间。您可以定期检查所有插座的时间,如果时间很久,则关闭连接。
另一种解决方案是在协议中包含“保持活动”消息。定期发送所有套接字上的“你还活着”消息。如果你在一段时间内没有收到“我还活着”的回复,那么连接可能会被认为是陈旧的,你可以关闭它。
为每个套接字使用单独的线程或进程。然后你可以使用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时间,并检查该循环是否超过了超时限制。