【问题标题】:Read, write and exception fd_set handling with select() in C在 C 中使用 select() 进行读取、写入和异常 fd_set 处理
【发布时间】:2020-03-04 14:21:01
【问题描述】:

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

if (select(fdmax+1, &read_fds, &write_fds, &except_fds, NULL) == -1) {
    perror("select()");
    exit(1);
} else {
    ...
}
  1. 一个特定的文件描述符是否可以同时进行读写和异常处理?

  2. Beej 的流行网络页面显示了一个 select() 示例,在该示例中,他使用 for 循环测试了 read fd_set 的成员。由于循环每次迭代都会递增 1,因此它必然会测试一些并非恰好是现有文件描述符的整数:

for(i = 0; i <= fdmax; i++) {
    if (FD_ISSET(i, &read_fds)) { // we got one!!
    {
        ...
    }
}

我相信他这样做是为了让示例代码保持简单。可能/应该只测试现有的文件描述符?

【问题讨论】:

  • 1.是的。 2. 是的,如果您将它们放在一个方便的数组中,或者只有一个,在这种情况下,为什么要使用select()?通常你没有这样的数组。
  • @user207421 当然,您可以使用select() 来找出哪些套接字当前是可读/可写/承载异常的,并且通常也会阻塞直到其中至少一个是。跨度>
  • 请注意,您需要在每次调用 select() 时设置 FD 集中的值,因为 select() 会修改提供的数据。这意味着您需要在某处将要放入 FD 集中的数字列表 - 该列表可用于控制检查应测试哪些 FD 的处理。
  • @JeremyFriesner 我不知道你为什么要告诉我select() 是如何工作的,或者当我有 30 年的使用经验并且我什么都没说的时候它是做什么用的这与您的评论相矛盾。我的问题是,当您只有 一个 套接字时,为什么要使用 select()。;

标签: c sockets select


【解决方案1】:

通过示例和@user207421 评论扩展一点:

1 一个特定的文件描述符可以同时进行读写和异常处理吗?

一个很好的例子是一个套接字,它(几乎)总是准备好写入,并且在数据可用时准备好读取。例外情况并不常见 - 它们用于exceptional 情况。例如,TCP 连接上的带外消息的可用性,但大多数应用程序不使用这些功能。

请注意,“正常”错误将在readfds 中指示(例如,套接字关闭)。

另见:*nix select and exceptfds/errorfds semantics

Beej 的流行网络页面显示了一个 select() 示例,在该示例中,他使用 for 循环测试了 read fd_set 的成员。由于循环每次迭代都会递增 1,因此它必然会测试一些并非恰好是现有文件描述符的整数:

我相信在这种情况下,它简化了代码示例,并且对于大多数轻量级实现来说是一个合理的实现。如果非监听连接的数量非常少,则效果很好。

值得一提的是,'fd_set' 在 Linux 上是通过一组位实现的,但在 Windows (winsock) 上是作为 fd 值的数组实现的。对所有 FD 的完整扫描在 Linux 上为 O(n),在 Windows 上为 O(n*n)。这会对大型 N for Windows 应用程序的性能造成很大影响。

在大型应用程序中,服务器将侦听数百(或更多)打开的连接,每个连接都需要不同的操作,可能具有多种状态,通常的做法是拥有活动连接的列表,并使用回调调用函数。这通常使用“事件循环”来实现。示例包括 X11、rpc 服务器等。

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

【讨论】:

  • 我没有说“为了简化”。对引用的文本使用引用格式。不要对非代码文本使用代码格式。
  • @user207421,抱歉,我将您的2. Yes 误解为对问题keeping the example code simple 的确认。
【解决方案2】:

您的问题:当您只有一个套接字时为什么要使用 select()。

当使用select 并且您不希望它阻止其他处理时。 然后使用 timeout 参数。

这样,即使只打开一个文件描述符,程序也不会因为一个文件描述符没有接收到任何数据而永远阻塞,因为如果使用read()或类似函数它会阻塞。

I.E.这是一个非常好的方法,例如监听一个串口,当一些外部事件发生时,串口才有数据。

【讨论】:

    猜你喜欢
    • 2014-05-21
    • 2022-06-17
    • 2011-07-13
    • 2011-02-16
    • 2016-05-12
    • 2010-10-25
    • 2020-04-18
    • 1970-01-01
    • 2011-02-17
    相关资源
    最近更新 更多