20.2. The SocketServer Module
The Python library supplies a framework module, SocketServer, to help you implement simple Internet servers. SocketServer supplies server classes TCPServer, for connection-oriented servers using TCP, and UDPServer, for datagram-oriented servers using UDP, with the same interface.
An instance s of either TCPServer or UDPServer supplies many attributes and methods, and you can subclass either class and override some methods to architect your own specialized server framework. However, I do not cover such advanced and rarely used possibilities in this book.
Classes TCPServer and UDPServer implement synchronous servers that can serve one request at a time. Classes ThreadingTCPServer and ThreadingUDPServer implement threaded servers, spawning a new thread per request. You are responsible for synchronizing the resulting threads as needed. Threading is covered in "Threads in Python" on page 341.
20.2.1. The BaseRequestHandler Class
For normal use of SocketServer, subclass the BaseRequestHandler class provided by SocketServer and override the handle method. Then instantiate a server class, passing the address pair on which to serve and your subclass of BaseRequestHandler. Finally, call serve_forever on the server instance.
An instance h of BaseRequestHandler supplies the following methods and attributes.
Example 20-5. Threaded TCP echo server using SocketServer
Run the server of Example 20-5 on a terminal window and try a few runs of Example 20-2. Try also telnet localhost 8881 on other terminal windows (or other platform-dependent Telnet-like programs) to verify the behavior of longer-lived connections.
20.2.2. HTTP Servers
188.8.131.52. The BaseHTTPServer module
The BaseHTTPServer module supplies a server class HTTPServer that subclasses SocketServer.TCPServer and is used in the same way. It also provides a request handler class BaseHTTPRequestHandler, which subclasses SocketServer.BaseRe-questHandler and adds attributes and methods useful for HTTP servers, of which the most commonly used are as follows.
As an example, here's a trivial HTTP server that answers every request with the 404 error code and the corresponding message 'File not found':
import BaseHTTPServer class TrivialHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """Trivial HTTP request handler, answers not found to every request""" server_version = "TrivialHTTP/1.0" def do_GET(self): """Serve a GET request.""" self.send_error(404, "File not found") do_HEAD = do_POST = do_GET server = BaseHTTPServer.HTTPServer((",80), TrivialHTTPRequestHandler) server.serve_forever( )
184.108.40.206. The SimpleHTTPServer module
The SimpleHTTPServer module builds on top of BaseHTTPServer, supplying what's needed to serve HTTP GET requests for files in a directory. It is most useful as an example of how to use BaseHTTPServer for a simple real-world HTTP serving task.
220.127.116.11. The CGIHTTPServer module
The CGIHTTPServer module builds on top of SimpleHTTPServer, supplying the ability to serve HTTP GET and POST requests via CGI scripts, covered in Chapter 19. You can use it, for example, to debug CGI scripts on your local machine.
18.104.22.168. The SimpleXMLRPCServer module
XML-RPC is a higher-level protocol that runs on top of HTTP. Python supports XML-RPC clients with module xmlrpclib, covered in "Distributed Computing" on page 516. The SimpleXMLRPCServer module supplies class SimpleXMLRPCServer to instantiate with the address pair on which to serve.
An instance x of class SimpleXMLRPCServer supplies two methods to call before x.serve_forever( ).
Simple examples of all typical usage patterns for SimpleXMLRPCServer are given in the docstring of module SimpleXMLRPCServer.py, which you can find in the Lib directory of your Python installation. Here is a toy example of using the _dispatch method. In one terminal window, run the following tiny script:
import SimpleXMLRPCServer class with_dispatch: def _dispatch(self, *args): print '_dispatch', args return args server = SimpleXMLRPCServer.SimpleXMLRPCServer(('localhost',8888)) server.register_instance(with_dispatch( )) server.serve_forever( )
From a Python interactive session on another terminal window of the same machine (or an IDLE interactive session on the same machine), you can now run:
>>> import xmlrpclib >>> proxy = xmlrpclib.ServerProxy('http://localhost:8888') >>> print proxy.whatever.method('any', 'args') ['whatever.method', ['any', 'args']]