如何找到在fdset中哪个套接字描述符变为无效

3
在服务器端,在readfds上执行select()时,会返回坏文件描述符错误。我该如何找到在fdset中哪个fd变为无效?
2个回答

1
通常情况下,当另一端关闭连接或发送RST段时,select 返回并标记相应的描述符准备好读取。 当您随后从它们执行read/recv时,将返回错误或EOF。
您还可以尝试使用strace工具(如果可用)进行调试。 它将帮助您跟踪哪些描述符被提供给select,以及使用哪些描述符read/recv

在代码中,一旦我遇到这个错误...如果我遍历fdset中的每个fd并对每个fd执行fcntl(),我能找到哪个fd变得无效了吗? - user1495948
通常情况下,您需要迭代所有在结果读取fdset中标记为就绪的描述符,并从它们读取所需的数据。如果在读取后出现-1(或0,表示对等方关闭了套接字),则意味着发生了错误,并且在下一次调用“select”之前不应将此描述符包括在读取fdset中。 - Maksim Skurydzin
不,如果在选择中出现错误,我会对fdset中的每个fd执行fcntl操作,这样有帮助吗? - user1495948
你可能会通过这种方式检测到描述符出现了问题,但我从未见过这种操作。如果select返回EBADF,通常意味着您提供了一个无效的描述符。它无效的原因(不存在的文件描述符、关闭的描述符或发生错误的描述符)应该在之前确定。 - Maksim Skurydzin

0
您可以使用以下函数检查套接字上的待处理错误:
int get_socket_error( int s )  {
    int error;
    socklen_t len = sizeof( error );
    if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &error, &len ) < 0 ) 
        error = errno;
    return error;
}

但是正如@Maxim所说,从select(2)返回EBADF通常表示代码质量较差。


好的,一个基本问题...是否可以遍历fdset..有人知道fdset的结构吗...找不到它。 - user1495948
通常,fdset是一个位图,其中每个位都显示描述符是否准备就绪。但是,您不应该依赖于fdset的内部实现,并使用宏来操作它(FD_ISSET等)。一种常见的方法是从0到max_fd + 1循环,使用FD_ISSET宏检查描述符是否准备好进行IO操作。您正在迭代的当前变量包含文件描述符。 - Maksim Skurydzin
如果你使用的是Linux操作系统,建议切换至epoll(7)。这样就不需要在每次迭代中重新填充等待列表了,而且已经被关闭的套接字会自动从轮询集合中删除。 - Nikolai Fetissov
好的,就 Windows 而言,我可以使用 ioctlsocket() 函数来检查套接字是否有效吗? - user1495948
也许我不了解Windows,但你正在尝试解决错误的问题——修复你的套接字处理。 - Nikolai Fetissov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接