1 """Generic socket server classes.
3 This module tries to capture the various aspects of defining a server:
6 - AF_INET: IP (Internet Protocol) sockets (default)
7 - AF_UNIX: Unix domain sockets
8 - others, e.g. AF_DECNET are conceivable (see <socket.h>
10 - SOCK_STREAM (reliable stream, e.g. TCP)
11 - SOCK_DGRAM (datagrams, e.g. UDP)
12 - client address verification before further looking at the request
13 (This is actually a hook for any processing that needs to look
14 at the request before anything else, e.g. logging)
15 - how to handle multiple requests:
16 - synchronous (one request is handled at a time)
17 - forking (each request is handled by a new process)
18 - threading (each request is handled by a new thread)
20 The classes in this module favor the server type that is simplest to
21 write: a synchronous TCP/IP server. This is bad class design, but
22 save some typing. (There's also the issue that a deep class hierarchy
23 slows down method lookups.)
25 There are four classes in an inheritance diagram that represent
26 synchronous servers of four types:
28 +-----------+ +------------------+
29 | TCPServer |------->| UnixStreamServer |
30 +-----------+ +------------------+
33 +-----------+ +--------------------+
34 | UDPServer |------->| UnixDatagramServer |
35 +-----------+ +--------------------+
37 Note that UnixDatagramServer derives from UDPServer, not from
38 UnixStreamServer -- the only difference between an IP and a Unix
39 stream server is the address family, which is simply repeated in both
42 Forking and threading versions of each type of server can be created
43 using the ForkingServer and ThreadingServer mix-in classes. For
44 instance, a threading UDP server class is created as follows:
46 class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
48 The Mix-in class must come first, since it overrides a method defined
51 To implement a service, you must derive a class from
52 BaseRequestHandler and redefine its handle() method. You can then run
53 various versions of the service by combining one of the server classes
54 with your request handler class.
56 The request handler class must be different for datagram or stream
57 services. This can be hidden by using the mix-in request handler
58 classes StreamRequestHandler or DatagramRequestHandler.
60 Of course, you still have to use your head!
62 For instance, it makes no sense to use a forking server if the service
63 contains state in memory that can be modified by requests (since the
64 modifications in the child process would never reach the initial state
65 kept in the parent process and passed to each child). In this case,
66 you can use a threading server, but you will probably have to use
67 locks to avoid two requests that come in nearly simultaneous to apply
68 conflicting changes to the server state.
70 On the other hand, if you are building e.g. an HTTP server, where all
71 data is stored externally (e.g. in the file system), a synchronous
72 class will essentially render the service "deaf" while one request is
73 being handled -- which may be for a very long time if a client is slow
74 to reqd all the data it has requested. Here a threading or forking
75 server is appropriate.
77 In some cases, it may be appropriate to process part of a request
78 synchronously, but to finish processing in a forked child depending on
79 the request data. This can be implemented by using a synchronous
80 server and doing an explicit fork in the request handler class's
83 Another approach to handling multiple simultaneous requests in an
84 environment that supports neither threads nor fork (or where these are
85 too expensive or inappropriate for the service) is to maintain an
86 explicit table of partially finished requests and to use select() to
87 decide which request to work on next (or whether to handle a new
88 incoming request). This is particularly important for stream services
89 where each client can potentially be connected for a long time (if
90 threads or subprocesses can't be used).
93 - Standard classes for Sun RPC (which uses either UDP or TCP)
94 - Standard mix-in classes to implement various authentication
95 and encryption schemes
96 - Standard framework for select-based multiplexing
99 - What to do with out-of-band data?
114 """Base class for various socket-based server classes.
116 Defaults to synchronous IP stream (i.e., TCP).
118 Methods for the caller:
120 - __init__(server_address, RequestHandlerClass)
122 - handle_request() # if you don't use serve_forever()
123 - fileno() -> int # for select()
125 Methods that may be overridden:
129 - get_request() -> request, client_address
130 - verify_request(request, client_address)
131 - process_request(request, client_address)
134 Methods for derived classes:
136 - finish_request(request, client_address)
138 Class variables that may be overridden by derived classes or
143 - request_queue_size (only for stream sockets)
149 - RequestHandlerClass
154 address_family
= socket
.AF_INET
156 socket_type
= socket
.SOCK_STREAM
158 request_queue_size
= 5
160 allow_reuse_address
= 0
162 def __init__(self
, server_address
, RequestHandlerClass
):
163 """Constructor. May be extended, do not override."""
164 self
.server_address
= server_address
165 self
.RequestHandlerClass
= RequestHandlerClass
166 self
.socket
= socket
.socket(self
.address_family
,
169 self
.server_activate()
171 def server_bind(self
):
172 """Called by constructor to bind the socket.
177 if self
.allow_reuse_address
:
178 self
.socket
.setsockopt(socket
.SOL_SOCKET
, socket
.SO_REUSEADDR
, 1)
179 self
.socket
.bind(self
.server_address
)
181 def server_activate(self
):
182 """Called by constructor to activate the server.
187 self
.socket
.listen(self
.request_queue_size
)
190 """Return socket file number.
192 Interface required by select().
195 return self
.socket
.fileno()
197 def serve_forever(self
):
198 """Handle one request at a time until doomsday."""
200 self
.handle_request()
202 # The distinction between handling, getting, processing and
203 # finishing a request is fairly arbitrary. Remember:
205 # - handle_request() is the top-level call. It calls
206 # get_request(), verify_request() and process_request()
207 # - get_request() is different for stream or datagram sockets
208 # - process_request() is the place that may fork a new process
209 # or create a new thread to finish the request
210 # - finish_request() instantiates the request handler class;
211 # this constructor will handle the request all by itself
213 def handle_request(self
):
214 """Handle one request, possibly blocking."""
216 request
, client_address
= self
.get_request()
219 if self
.verify_request(request
, client_address
):
221 self
.process_request(request
, client_address
)
223 self
.handle_error(request
, client_address
)
225 def get_request(self
):
226 """Get the request and client address from the socket.
231 return self
.socket
.accept()
233 def verify_request(self
, request
, client_address
):
234 """Verify the request. May be overridden.
236 Return true if we should proceed with this request.
241 def process_request(self
, request
, client_address
):
242 """Call finish_request.
244 Overridden by ForkingMixIn and ThreadingMixIn.
247 self
.finish_request(request
, client_address
)
249 def finish_request(self
, request
, client_address
):
250 """Finish one request by instantiating RequestHandlerClass."""
251 self
.RequestHandlerClass(request
, client_address
, self
)
253 def handle_error(self
, request
, client_address
):
254 """Handle an error gracefully. May be overridden.
256 The default is to print a traceback and continue.
260 print 'Exception happened during processing of request from',
263 traceback
.print_exc()
267 class UDPServer(TCPServer
):
269 """UDP server class."""
271 socket_type
= socket
.SOCK_DGRAM
273 max_packet_size
= 8192
275 def get_request(self
):
276 data
, client_addr
= self
.socket
.recvfrom(self
.max_packet_size
)
277 return (data
, self
.socket
), client_addr
279 def server_activate(self
):
280 # No need to call listen() for UDP.
286 """Mix-in class to handle each request in a new process."""
288 active_children
= None
291 def collect_children(self
):
292 """Internal routine to wait for died children."""
293 while self
.active_children
:
294 if len(self
.active_children
) < self
.max_children
:
297 # If the maximum number of children are already
298 # running, block while waiting for a child to exit
301 pid
, status
= os
.waitpid(0, options
)
305 self
.active_children
.remove(pid
)
307 def process_request(self
, request
, client_address
):
308 """Fork a new subprocess to process the request."""
309 self
.collect_children()
313 if self
.active_children
is None:
314 self
.active_children
= []
315 self
.active_children
.append(pid
)
319 # This must never return, hence os._exit()!
322 self
.finish_request(request
, client_address
)
326 self
.handle_error(request
,
332 class ThreadingMixIn
:
333 """Mix-in class to handle each request in a new thread."""
335 def process_request(self
, request
, client_address
):
336 """Start a new thread to process the request."""
338 t
= threading
.Thread(target
= self
.finish_request
,
339 args
= (request
, client_address
))
343 class ForkingUDPServer(ForkingMixIn
, UDPServer
): pass
344 class ForkingTCPServer(ForkingMixIn
, TCPServer
): pass
346 class ThreadingUDPServer(ThreadingMixIn
, UDPServer
): pass
347 class ThreadingTCPServer(ThreadingMixIn
, TCPServer
): pass
349 if hasattr(socket
, 'AF_UNIX'):
351 class UnixStreamServer(TCPServer
):
352 address_family
= socket
.AF_UNIX
354 class UnixDatagramServer(UDPServer
):
355 address_family
= socket
.AF_UNIX
357 class ThreadingUnixStreamServer(ThreadingMixIn
, UnixStreamServer
): pass
359 class ThreadingUnixDatagramServer(ThreadingMixIn
, UnixDatagramServer
): pass
361 class BaseRequestHandler
:
363 """Base class for request handler classes.
365 This class is instantiated for each request to be handled. The
366 constructor sets the instance variables request, client_address
367 and server, and then calls the handle() method. To implement a
368 specific service, all you need to do is to derive a class which
369 defines a handle() method.
371 The handle() method can find the request as self.request, the
372 client address as self.client_address, and the server (in case it
373 needs access to per-server information) as self.server. Since a
374 separate instance is created for each request, the handle() method
375 can define arbitrary other instance variariables.
379 def __init__(self
, request
, client_address
, server
):
380 self
.request
= request
381 self
.client_address
= client_address
388 sys
.exc_traceback
= None # Help garbage collection
403 # The following two classes make it possible to use the same service
404 # class for stream or datagram servers.
405 # Each class sets up these instance variables:
406 # - rfile: a file object from which receives the request is read
407 # - wfile: a file object to which the reply is written
408 # When the handle() method returns, wfile is flushed properly
411 class StreamRequestHandler(BaseRequestHandler
):
413 """Define self.rfile and self.wfile for stream sockets."""
416 self
.connection
= self
.request
417 self
.rfile
= self
.connection
.makefile('rb', 0)
418 self
.wfile
= self
.connection
.makefile('wb', 0)
426 class DatagramRequestHandler(BaseRequestHandler
):
428 """Define self.rfile and self.wfile for datagram sockets."""
432 self
.packet
, self
.socket
= self
.request
433 self
.rfile
= StringIO
.StringIO(self
.packet
)
434 self
.wfile
= StringIO
.StringIO(self
.packet
)
437 self
.socket
.sendto(self
.wfile
.getvalue(), self
.client_address
)