Commit 766349e5 authored by Skip Montanaro's avatar Skip Montanaro

Incorporate a lightly edited version of the SocketServer module's docstring

into the docs and segregate the method descriptions for the various classes
into separate sections.  Base on suggestion by Paul Rubin in c.l.py.
parent 935ea9a0
...@@ -52,10 +52,87 @@ matter what network protocol they use: ...@@ -52,10 +52,87 @@ matter what network protocol they use:
\setindexsubitem{(SocketServer protocol)} \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? %XXX should data and methods be intermingled, or separate?
% how should the distinction between class and instance variables be % how should the distinction between class and instance variables be
% drawn? % drawn?
\subsection{Server Objects}
\begin{funcdesc}{fileno}{} \begin{funcdesc}{fileno}{}
Return an integer file descriptor for the socket on which the server Return an integer file descriptor for the socket on which the server
is listening. This function is most commonly passed to is listening. This function is most commonly passed to
...@@ -160,7 +237,8 @@ and \class{ThreadingMixIn} classes do this. ...@@ -160,7 +237,8 @@ and \class{ThreadingMixIn} classes do this.
% instance variables, adding new network families? % instance variables, adding new network families?
\begin{funcdesc}{server_activate}{} \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. May be overridden.
\end{funcdesc} \end{funcdesc}
...@@ -176,6 +254,8 @@ This function can be overridden to implement access controls for a server. ...@@ -176,6 +254,8 @@ This function can be overridden to implement access controls for a server.
The default implementation always returns \constant{True}. The default implementation always returns \constant{True}.
\end{funcdesc} \end{funcdesc}
\subsection{RequestHandler Objects}
The request handler class must define a new \method{handle()} method, The request handler class must define a new \method{handle()} method,
and can override any of the following methods. A new instance is and can override any of the following methods. A new instance is
created for each request. created for each request.
...@@ -189,6 +269,7 @@ function will not be called. ...@@ -189,6 +269,7 @@ function will not be called.
\begin{funcdesc}{handle}{} \begin{funcdesc}{handle}{}
This function must do all the work required to service a request. 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 Several instance attributes are available to it; the request is
available as \member{self.request}; the client address as available as \member{self.request}; the client address as
\member{self.client_address}; and the server instance as \member{self.client_address}; and the server instance as
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment