This server uses the age-old Berkeley select() function to manage many connections within a single thread. This style of server has two big advantages over the multithreaded server: it doesn't have all the context switching overhead associated with threads, and the code is easy to port to nearly all flavors of Unix. The cost you pay for these benefits is that there's roughly twice as much code as in the threaded server.

The major difference between this server and the threaded server is that all the I/O in this version is handled in the AcceptConnections() function, rather than in a bunch of concurrent threads. In fact, AcceptConnection() is pretty much the main function in this version, whereas in the threaded server, it just accepts connections and passes them off to handler threads.

Notice that we have to keep a list of clients and an I/O buffer for each client in this version. That's the price of non-synchronous I/O: you have to keep a lot of state around so you can juggle between many connections within a single thread.

Also notice that we do not call WSAGetLastError() in this program, but instead call getsockopt() asking for the SO_ERROR value. With select(), several sockets can go into an error state at once, so the "last" error is not necessarily the error value we're interested in. We have to find the last error that occured on a particular socket instead.

Building the Program

The only module you will need to compile this program, aside from the common files listed on the main examples page, is select-server.cpp. The comment at the top of the file gives complete compilation instructions; alternately, you can use the common Makefile.

<< Multithreaded Server
Ping: ICMP.DLL Method >>
Updated Fri Dec 16 2022 12:23 MST   Go to my home page