c - 在 C 中使用 select() 读取、写入和异常 fd_set 处理

标签 c sockets select

如果我使用 select() 来监视三个文件描述符集:

if (select(fdmax+1, &read_fds, &write_fds, &except_fds, NULL) == -1) {
    perror("select()");
    exit(1);
} else {
    ...
}
  1. 特定的文件描述符能否同时准备好读取、写入和异常处理?

  2. 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 服务器等。

另请参阅:https://en.wikipedia.org/wiki/Event_loop

关于c - 在 C 中使用 select() 读取、写入和异常 fd_set 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58758285/

相关文章:

c - 如何理解带有指针的字符串

c - close() 优于 shutdown() 的任何情况?

c# - Java 相当于 C# Stream.BeginRead() 和 AsyncResult?

c++ - 套接字编程中的select()c++总是给出时间错误

mysql - SQL - 从组中检索平均分数

javascript - 选项.删除();不起作用,奇怪的行为

c - 如何回调赋予一个函数的值以在不同的函数中使用

c - 等子孙

java - Java 中的 SSL 套接字

c - 在不使用其他功能的情况下释放 C 扩展中的全局 VM 锁