supports both clients and servers and includes implementations of a number of
commonly used network services such as a web server, an IRC chat server, a mail
server, a relational database interface, and an object broker.
Although Twisted supports processes and threads for longer-running actions, it
also uses an asynchronous, event-driven model to handle clients, which is similar
to the event loop of GUI libraries like tkinter. It abstracts an event loop, which
multiplexes among open socket connections, automates many of the details in-
herent in an asynchronous server, and provides an event-driven framework for
scripts to use to accomplish application tasks. Twisted’s internal event engine is
similar in spirit to our select-based server and the asyncore module, but it is re-
garded as much more advanced. Twisted is a third-party system, not a standard
library tool; see its website and documentation for more details.
Summary: Choosing a Server Scheme
So when should you use select to build a server, instead of threads or forks? Needs
vary per application, of course, but as mentioned, servers based on the select call
generally perform very well when client transactions are relatively short and are not
CPU-bound. If they are not short, threads or forks may be a better way to split pro-
cessing among multiple clients. Threads and forks are especially useful if clients require
long-running processing above and beyond the socket calls used to pass data. However,
combinations are possible too—nothing is stopping a select-based polling loop from
using threads, too.
It’s important to remember that schemes based on select (and nonblocking sockets)
are not completely immune to blocking. In Example 12-9, for instance, the send call
that echoes text back to a client might block, too, and hence stall the entire server. We
could work around that blocking potential by using select to make sure that the output
operation is ready before we attempt it (e.g., use the writesocks list and add another
loop to send replies to ready output sockets), albeit at a noticeable cost in program
clarity.
In general, though, if we cannot split up the processing of a client’s request in such a
way that it can be multiplexed with other requests and not block the server’s main loop,
select may not be the best way to construct a server by itself. While some network
servers can satisfy this constraint, many cannot.
Moreover, select also seems more complex than spawning either processes or threads,
because we need to manually transfer control among all tasks (for instance, compare
the threaded and select versions of our echo server, even without write selects). As
usual, though, the degree of that complexity varies per application. The asyncore
standard library module mentioned earlier simplifies some of the tasks of implementing
a select-based event-loop socket server, and Twisted offers additional hybrid
solutions.
826 | Chapter 12: Network Scripting