如果我使用 select() 来监视三个文件描述符集:
if (select(fdmax+1, &read_fds, &write_fds, &except_fds, NULL) == -1) {
perror("select()");
exit(1);
} else {
...
}
特定的文件描述符能否同时准备好读取、写入和异常处理?
Beej 的热门网络页面显示了一个 select() 示例,在该示例中,他使用 for 循环测试读取 fd_set 的成员。由于循环每次迭代递增 1,因此它必然会测试一些恰好不是现有文件描述符的整数:
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
{
...
}
}
我相信他这样做是为了让示例代码保持简单。可能/应该只测试现有的文件描述符吗?
最佳答案
通过示例和@user207421 评论进行一些扩展:
1 Can a particular file descriptor be ready for reading AND writing AND exception handling simultaneously?
套接字就是一个很好的例子,它(几乎)总是准备好写入,并在数据可用时准备好读取。出现异常并不常见 - 它们用于 exceptional
情况。例如,TCP 连接上带外消息的可用性,但大多数应用程序不使用这些功能。
请注意,“正常”错误将在 readfds
中指示(例如,套接字关闭)。
另请参阅:*nix select and exceptfds/errorfds semantics ,
Beej's popular networking page shows a select() example in which he tests the members of the read fd_set using a for loop. Since the loop increments by one each iteration, it will necessarily test some integers that don't happen to be existing file descriptors:
我相信在这种情况下,它已经简化了代码示例,并且对于大多数轻量级实现来说是一个合理的实现。如果非监听连接的数量非常少,它会很好地工作。
值得一提的是,“fd_set”在 Linux 上使用一组位实现,但在 Windows (winsock) 上作为 fd 值数组实现。对所有 FD 的完整扫描在 Linux 上为 O(n),在 Windows 上为 O(n*n)。这会对 large N for Windows 应用程序产生很大的性能影响。
在大型应用程序中,服务器将监听数百(或更多)打开的连接,每个连接都需要不同的操作,可能具有多个状态,通常的做法是获取事件连接列表,并使用回调调用函数。这通常使用“事件循环”来实现。示例包括 X11、rpc 服务器等。
关于c - 在 C 中使用 select() 读取、写入和异常 fd_set 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58758285/