[Python-checkins] python/dist/src/Doc/lib libsocksvr.tex, 1.18, 1.18.4.1

montanaro@users.sourceforge.net montanaro at users.sourceforge.net
Thu May 12 15:43:42 CEST 2005


Update of /cvsroot/python/python/dist/src/Doc/lib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1594

Modified Files:
      Tag: release24-maint
	libsocksvr.tex 
Log Message:
backport from head


Index: libsocksvr.tex
===================================================================
RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsocksvr.tex,v
retrieving revision 1.18
retrieving revision 1.18.4.1
diff -u -d -r1.18 -r1.18.4.1
--- libsocksvr.tex	21 Jul 2004 02:47:10 -0000	1.18
+++ libsocksvr.tex	12 May 2005 13:43:40 -0000	1.18.4.1
@@ -52,10 +52,87 @@
 
 \setindexsubitem{(SocketServer protocol)}
 
+\subsection{Server Creation Notes}
+
+There are five classes in an inheritance diagram, four of which represent
+synchronous servers of four types:
+
+\begin{verbatim}
+        +------------+
+        | BaseServer |
+        +------------+
+              |
+              v
+        +-----------+        +------------------+
+        | TCPServer |------->| UnixStreamServer |
+        +-----------+        +------------------+
+              |
+              v
+        +-----------+        +--------------------+
+        | UDPServer |------->| UnixDatagramServer |
+        +-----------+        +--------------------+
+\end{verbatim}
+
+Note that \class{UnixDatagramServer} derives from \class{UDPServer}, not
+from \class{UnixStreamServer} -- the only difference between an IP and a
+Unix stream server is the address family, which is simply repeated in both
+unix server classes.
+
+Forking and threading versions of each type of server can be created using
+the \class{ForkingMixIn} and \class{ThreadingMixIn} mix-in classes.  For
+instance, a threading UDP server class is created as follows:
+
+\begin{verbatim}
+    class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
+\end{verbatim}
+
+The mix-in class must come first, since it overrides a method defined in
+\class{UDPServer}.  Setting the various member variables also changes the
+behavior of the underlying server mechanism.
+
+To implement a service, you must derive a class from
+\class{BaseRequestHandler} and redefine its \method{handle()} method.  You
+can then run various versions of the service by combining one of the server
+classes with your request handler class.  The request handler class must be
+different for datagram or stream services.  This can be hidden by using the
+mix-in request handler classes \class{StreamRequestHandler} or
+\class{DatagramRequestHandler}.
+
+Of course, you still have to use your head!  For instance, it makes no sense
+to use a forking server if the service contains state in memory that can be
+modified by different requests, since the modifications in the child process
+would never reach the initial state kept in the parent process and passed to
+each child.  In this case, you can use a threading server, but you will
+probably have to use locks to protect the integrity of the shared data.
+
+On the other hand, if you are building an HTTP server where all data is
+stored externally (for instance, in the file system), a synchronous class
+will essentially render the service "deaf" while one request is being
+handled -- which may be for a very long time if a client is slow to receive
+all the data it has requested.  Here a threading or forking server is
+appropriate.
+
+In some cases, it may be appropriate to process part of a request
+synchronously, but to finish processing in a forked child depending on the
+request data.  This can be implemented by using a synchronous server and
+doing an explicit fork in the request handler class \method{handle()}
+method.
+
+Another approach to handling multiple simultaneous requests in an
+environment that supports neither threads nor \function{fork()} (or where
+these are too expensive or inappropriate for the service) is to maintain an
+explicit table of partially finished requests and to use \function{select()}
+to decide which request to work on next (or whether to handle a new incoming
+request).  This is particularly important for stream services where each
+client can potentially be connected for a long time (if threads or
+subprocesses cannot be used).
+
 %XXX should data and methods be intermingled, or separate?
 % how should the distinction between class and instance variables be
 % drawn?
 
+\subsection{Server Objects}
+
 \begin{funcdesc}{fileno}{}
 Return an integer file descriptor for the socket on which the server
 is listening.  This function is most commonly passed to
@@ -160,7 +237,8 @@
 % instance variables, adding new network families?
 
 \begin{funcdesc}{server_activate}{}
-Called by the server's constructor to activate the server.
+Called by the server's constructor to activate the server.  The default
+behavior just \method{listen}s to the server's socket.
 May be overridden.
 \end{funcdesc}
 
@@ -176,6 +254,8 @@
 The default implementation always returns \constant{True}.
 \end{funcdesc}
 
+\subsection{RequestHandler Objects}
+
 The request handler class must define a new \method{handle()} method,
 and can override any of the following methods.  A new instance is
 created for each request.
@@ -189,6 +269,7 @@
 
 \begin{funcdesc}{handle}{}
 This function must do all the work required to service a request.
+The default implementation does nothing.
 Several instance attributes are available to it; the request is
 available as \member{self.request}; the client address as
 \member{self.client_address}; and the server instance as



More information about the Python-checkins mailing list