Client received: b"Echo=>b'Brian' at Sun Apr 25 12:41:52 2010"
C:\...\PP4E\Internet\Sockets> python echo-client.py localhost Bright side of life
Client received: b"Echo=>b'Bright' at Sun Apr 25 12:41:54 2010"
Client received: b"Echo=>b'side' at Sun Apr 25 12:41:54 2010"
Client received: b"Echo=>b'of' at Sun Apr 25 12:41:54 2010"
Client received: b"Echo=>b'life' at Sun Apr 25 12:41:54 2010"
Remember that a thread silently exits when the function it is running returns; unlike
the process fork version, we don’t call anything like os._exit in the client handler func-
tion (and we shouldn’t—it may kill all threads in the process, including the main loop
watching for new connections!). Because of this, the thread version is not only more
portable, but also simpler.
Standard Library Server Classes
Now that I’ve shown you how to write forking and threading servers to process clients
without blocking incoming requests, I should also tell you that there are standard tools
in the Python standard library to make this process even easier. In particular, the
socketserver module defines classes that implement all flavors of forking and threading
servers that you are likely to be interested in.
Like the manually-coded servers we’ve just studied, this module’s primary classes im-
plement servers which process clients in parallel (a.k.a. asynchronously) to avoid de-
nying service to new requests during long-running transactions. Their net effect is to
automate the top-levels of common server code. To use this module, simply create the
desired kind of imported server object, passing in a handler object with a callback
method of your own, as demonstrated in the threaded TCP server of Example 12-8.
Example 12-8. PP4E\Internet\Sockets\class-server.py
"""
Server side: open a socket on a port, listen for a message from a client, and
send an echo reply; this version uses the standard library module socketserver to
do its work; socketserver provides TCPServer, ThreadingTCPServer, ForkingTCPServer,
UDP variants of these, and more, and routes each client connect request to a new
instance of a passed-in request handler object's handle method; socketserver also
supports Unix domain sockets, but only on Unixen; see the Python library manual.
"""
import socketserver, time # get socket server, handler objects
myHost = '' # server machine, '' means local host
myPort = 50007 # listen on a non-reserved port number
def now():
return time.ctime(time.time())
class MyClientHandler(socketserver.BaseRequestHandler):
def handle(self): # on each client connect
print(self.client_address, now()) # show this client's address
time.sleep(5) # simulate a blocking activity
while True: # self.request is client socket
818 | Chapter 12: Network Scripting