THE WORLD OF SELECT()

So just why am I so hyped on select()?

One traditional way to write network servers is to have the main server
block on accept(), waiting for a connection. Once a connection
comes in, the server fork()s, the child process handles the connection
and the main server is able to service new incoming requests.

With select(), instead of having a process for each request, there is
usually only one process that "multi-plexes" all requests,
servicing each request as much as it can.

So one main advantage of using select() is that your server will only require
a single process to handle all requests. Thus, your server will not need shared
memory or synchronization primitives for different 'tasks' to communicate.

One major disadvantage of using select(), is that your server cannot act like
there's only one client, like with a fork()'ing solution. For example, with a
fork()'ing solution, after the
server fork()s, the child process works with the client as if there was only one
client in the universe -- the child does not have to worry about new incoming
connections or the existence of other sockets. With select(), the programming
isn't as transparent.

Okay, so how do you use select()?

select() works by blocking until something happens on a file descriptor
(aka a socket). What's 'something'? Data coming in or being able to
write to a file descriptor -- you tell
select() what you want to be woken up by. How do you tell it? You fill
up a fd_set structure with some macros.

Most select()-based servers look pretty much the same:

Fill up a fd_set structure with the file descriptors
you want to know when data comes in on.

Fill up a fd_set structure with the file descriptors
you want to know when you can write on.

Call select() and block until something happens.

Once select() returns, check to see if any of your
file descriptors was the reason you woke up. If so, 'service' that
file descriptor in whatever particular way your server needs to
(i.e. read in a request for a Web page).