简体   繁体   English

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

[英]Read, write and exception fd_set handling with select() in C

If I am using select() to monitor three file descriptor sets:如果我使用 select() 来监视三个文件描述符集:

if (select(fdmax+1, &read_fds, &write_fds, &except_fds, NULL) == -1) {
    perror("select()");
    exit(1);
} else {
    ...
}
  1. Can a particular file descriptor be ready for reading AND writing AND exception handling simultaneously?一个特定的文件描述符可以同时进行读写和异常处理吗?

  2. Beej's popular networking page shows a select() example in which he tests the members of the read fd_set using a for loop. Beej 的流行网络页面显示了一个 select() 示例,在该示例中,他使用 for 循环测试了 read fd_set 的成员。 Since the loop increments by one each iteration, it will necessarily test some integers that don't happen to be existing file descriptors:由于循环每次迭代都会递增 1,因此它必然会测试一些并非恰好是现有文件描述符的整数:

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

I believe he's doing this for the sake of keeping the example code simple.我相信他这样做是为了使示例代码保持简单。 Might/should one only test existing file descriptors?可能/应该只测试现有的文件描述符?

Expanding a little bit with examples and @user207421 comment:通过示例和@user207421 评论扩展一点:

1 Can a particular file descriptor be ready for reading AND writing AND exception handling simultaneously? 1 一个特定的文件描述符可以同时进行读写和异常处理吗?

Good example will be a socket, which will (almost) always be ready for writing, and will be ready for reading when data is available.一个很好的例子是一个套接字,它(几乎)总是准备好写入,并且在数据可用时准备好读取。 It is not common to have exceptions - they are used for exceptional situations.例外情况并不常见——它们用于exceptional情况。 For example, availability of out-of-band message on TCP connections, but most applications do not use those features.例如,TCP 连接上的带外消息的可用性,但大多数应用程序不使用这些功能。

Note that 'normal' errors will be indicated in readfds (for example, socket shutdown).请注意,“正常”错误将在readfds中指示(例如,套接字关闭)。

See also: *nix select and exceptfds/errorfds semantics ,另请参阅: *nix select 和 exceptfds/errorfds 语义

Beej's popular networking page shows a select() example in which he tests the members of the read fd_set using a for loop. Beej 的流行网络页面显示了一个 select() 示例,在该示例中,他使用 for 循环测试了 read fd_set 的成员。 Since the loop increments by one each iteration, it will necessarily test some integers that don't happen to be existing file descriptors:由于循环每次迭代都会递增 1,因此它必然会测试一些并非恰好是现有文件描述符的整数:

I believe that in this case, it is done simplify the code examples, and is a reasonable implementation for most light weight implementations.我相信在这种情况下,它简化了代码示例,并且对于大多数轻量级实现来说是一个合理的实现。 It works well if the number of non-listen connections is very small.如果非侦听连接的数量非常少,则效果很好。

Worth mentioning that the 'fd_set' is implemented on Linux with a set of bits, but on Windows (winsock) as an array of fd values.值得一提的是,“fd_set”是在 Linux 上用一组位实现的,但在 Windows (winsock) 上是作为 fd 值的数组实现的。 A full scan on all FDs will be O(n) on Linux, and O(n*n) on Windows.对所有 FD 的完整扫描在 Linux 上为 O(n),在 Windows 上为 O(n*n)。 This can make a big performance hit on large N for Windows app.这会对 Windows 应用程序的大 N 造成很大的影响。

In large scale applications, where a server will listen to hundreds (or more) open connections, each require different actions, potentially with multiple states, the common practice will be to have the list of of active connections, and use a callback to invoke the function.在大型应用程序中,服务器将侦听数百个(或更多)打开的连接,每个连接都需要不同的操作,可能具有多种状态,通常的做法是拥有活动连接的列表,并使用回调来调用function。 This is usually implemented with an 'eventloop'.这通常使用“事件循环”来实现。 Examples include X11, rpc servers, etc.示例包括 X11、rpc 服务器等。

See Also: https://en.wikipedia.org/wiki/Event_loop另见: https://en.wikipedia.org/wiki/Event_loop

Your question: why you would use select() when you only have one socket.您的问题:当您只有一个套接字时,为什么要使用 select() 。

when select is used and you do not want it to block other processing.当使用select并且您不希望它阻止其他处理时。 Then make use of the timeout parameter.然后使用 timeout 参数。

That way, even with only one file descriptor open, The program will not block forever due to that one file descriptor not receiving any data as it would block if using read() or similar function.这样,即使只打开一个文件描述符,程序也不会因为一个文件描述符没有接收任何数据而永远阻塞,因为如果使用read()或类似的 function 会阻塞。

IE this is a very good method when, for instance, listening to a serial port, which only has data when some external event occurs. IE 是一个非常好的方法,例如,监听一个串口,当一些外部事件发生时,串口只有数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM