0

If I am using select() to monitor three file descriptor sets:

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. Since the loop increments by one each iteration, it will necessarily test some integers that don't happen to be existing file descriptors:

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?

user207421
  • 305,947
  • 44
  • 307
  • 483
EdH
  • 33
  • 4
  • 1. Yes. 2. Yes, if you have them handy in an array, or there is only one of them, in which case why use `select()` at all? Usually you don't have such an array. – user207421 Nov 08 '19 at 03:48
  • @user207421 You'd use `select()` to find out which sockets are currently readable/writeable/exception-bearing, of course, and commonly also to block until at least one of them is. – Jeremy Friesner Nov 08 '19 at 05:32
  • 1
    Note that you need a way to set the values in the FD-sets on each call to `select()` because `select()` modifies the data provided. That means you need somewhere a list of the numbers to be put into the FD-set — and that list could be used to control the processing that checks on which FDs should be tested. – Jonathan Leffler Nov 08 '19 at 05:40
  • @JeremyFriesner I don't know why you're trying to tell me how `select()` works or what it is for when I have 30 years' experience using it and when I haven't said anything that is contradicted by your comment. My question was why you would use `select()` when you only have *one* socket.; – user207421 Nov 08 '19 at 10:03

2 Answers2

3

Expanding a little bit with examples and @user207421 comment:

1 Can a particular file descriptor be ready for reading AND writing AND exception handling simultaneously?

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. For example, availability of out-of-band message on TCP connections, but most applications do not use those features.

Note that 'normal' errors will be indicated in readfds (for example, socket shutdown).

See also: *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:

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. A full scan on all FDs will be O(n) on Linux, and O(n*n) on Windows. This can make a big performance hit on large N for Windows app.

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. This is usually implemented with an 'eventloop'. Examples include X11, rpc servers, etc.

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

dash-o
  • 13,723
  • 1
  • 10
  • 37
  • I didn't say anything about 'for simplification'. Use quote formatting for text that is quoted. Don't use code formatting for text that isn't code. – user207421 Nov 08 '19 at 05:00
  • @user207421, sorry, I misinterpret your `2. Yes` as confirmation to the question `keeping the example code simple`. – dash-o Nov 08 '19 at 06:02
0

Your question: why you would use select() when you only have one socket.

when select is used and you do not want it to block other processing. Then make use of the timeout parameter.

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.

I.E. this is a very good method when, for instance, listening to a serial port, which only has data when some external event occurs.

user3629249
  • 16,402
  • 1
  • 16
  • 17