removed obsolete issues (many of them fixed with AE)
[docutils.git] / sandbox / edloper / docpy / asyncore.rst
blob2eda1647c232cb891835e66e4e24e25cdecd3200
1 ==========
2  asyncore
3 ==========
5 -----------------------------
6  Asynchronous socket handler
7 -----------------------------
9 Literal block::
10   Synopsis: A base class for developing asynchronous socket
11             handling services.
12   Type: module builtin
13   Module-Author: Sam Rushing <rushing@nightmare.com>
14   Author: Christopher Petrilli <petrilli@amber.org>
15   Author: Steve Holden <sholden@holdenweb.com>
17 .. Type: ... builtin, standard, various others: any specific usages required?
19 .. Heavily adapted from original documentation by Sam Rushing.
21 ..  ............................................
22 ..   This is the (first) RFC822-reader strawman
23 ..  ............................................
24 ..    Presumes a custom reader appropriate to docpy
25 ..    RFC822 continuation IS allowed (see Synopsis)
26 ..    Needtocheck: RFC822-readers and multiple entities?  (Author lines)
27 ..    Dunno about implication of \section in the original
28 ..    Dunno about comments (#?);  "Credit: Sam Rushing?"
29 ..    Note in passing: names of new roles and directives made similar to
30 ..      the existing docpy macros on purpose (for existing corpus & community)
31 ..                  
32 ..    Markups needed, used, and existing in rst:
33 ..      *emphasis*
35 ..    Markups needed, used, and modified by this strawman:
36 ..      ``code``
37 ..    
38 ..    Roles needed below by this strawman:
39 ..      :cfunction:``
40 ..      :module:``
41 ..      :refmodule:``
42 ..      :class:``
43 ..      :function:``
44 ..      :var:``
45 ..      :label:``
46 ..    
47 ..    Directives needed below by this strawman:
48 ..      .. funcdesc::
49 ..              need to parse for optional argumnents shown as [...]
50 ..      .. classdesc::
51 ..      .. datadesc::
53 ..    TBS - formals, e.g., funcdesc - several alternatives proposed
54 ..              below (see funcdesc) in this draft 
55 ..          the one shown first seems on track for consensus 04.3.20
56 ..              (the directive will parse brackets, etc. - easier to use!)
58 This module provides the basic infrastructure for writing asynchronous 
59 socket service clients and servers.
61 There are only two ways to have a program on a single processor do 
62 "more than one thing at a time." Multi-threaded programming is the 
63 simplest and most popular way to do it, but there is another very 
64 different technique, that lets you have nearly all the advantages of 
65 multi-threading, without actually using multiple threads.  It's really 
66 only practical if your program is largely I/O bound.  If your program 
67 is processor bound, then pre-emptive scheduled threads are probably what 
68 you really need. Network servers are rarely processor bound, however.
70 If your operating system supports the :cfunction:`select()` system call 
71 in its I/O library (and nearly all do), then you can use it to juggle 
72 multiple communication channels at once; doing other work while your 
73 I/O is taking place in the "background."  Although this strategy can 
74 seem strange and complex, especially at first, it is in many ways 
75 easier to understand and control than multi-threaded programming.  
76 The :module:`asyncore` module solves many of the difficult problems for 
77 you, making the task of building sophisticated high-performance 
78 network servers and clients a snap. For "conversational" applications
79 and protocols the companion  :refmodule:`asynchat` module is invaluable.
81 The basic idea behind both modules is to create one or more network
82 *channels*, instances of class :class:`asyncore.dispatcher` and
83 :class:`asynchat.async_chat`. Creating the channels adds them to a global
84 map, used by the :function:`loop()` function if you do not provide it
85 with your own :var:`map`.
87 Once the initial channel(s) is(are) created, calling the :function:`loop()`
88 function activates channel service, which continues until the last
89 channel (including any that have been added to the map during asynchronous
90 service) is closed.
92 .. funcdesc:: loop([timeout [, use_poll [, map]]])
94     Enter a polling loop that only terminates after all open channels
95     have been closed.  All arguments are optional.  The :var:`timeout`
96     argument sets the timeout parameter for the appropriate
97     :function:`select()` or :function:`poll()` call, measured in seconds;
98     the default is 30 seconds.  The :var:`use_poll` parameter, if true,
99     indicates that :function:`poll()` should be used in preference to
100     :function:`select()` (the default is ``False``).  The :var:`map` parameter
101     is a dictionary whose items are the channels to watch.  As channels
102     are closed they are deleted from their map.  If :var:`map` is
103     omitted, a global map is used (this map is updated by the default
104     class :method:`__init__()`
105     -- make sure you extend, rather than override, :method:`__init__()`
106     if you want to retain this behavior).
108     Channels (instances of :class:`asyncore.dispatcher`, :class:`asynchat.async_chat`
109     and subclasses thereof) can freely be mixed in the map.
110     
111 .. classdesc:: dispatcher()
113     The :class:`dispatcher` class is a thin wrapper around a low-level socket object.
114     To make it more useful, it has a few methods for event-handling  which are called
115     from the asynchronous loop.  
116     Otherwise, it can be treated as a normal non-blocking socket object.
118     Two class attributes can be modified, to improve performance,
119     or possibly even to conserve memory.
121     .. datadesc:: ac_in_buffer_size
123         The asynchronous input buffer size (default ``4096``).
125     .. datadesc:: ac_out_buffer_size
127         The asynchronous output buffer size (default ``4096``).
129     The firing of low-level events at certain times or in certain connection
130     states tells the asynchronous loop that certain higher-level events have
131     taken place. For example, if we have asked for a socket to connect to
132     another host, we know that the connection has been made when the socket
133     becomes writable for the first time (at this point you know that you may
134     write to it with the expectation of success). The implied higher-level
135     events are:
136   
137     =====================       ===============================================
138     ``Event``                   Description
139     ---------------------       -----------------------------------------------
140     ``handle_connect()``        Implied by the first write event
141     ``handle_close()``          Implied by a read event with no data available
142     ``handle_accept()``         Implied by a read event on a listening socket
143     =====================       ===============================================
145   
146     During asynchronous processing, each mapped channel's :method:`readable()`
147     and :method:`writable()` methods are used to determine whether the channel's
148     socket should be added to the list of channels :cfunction:`select()`\ ed or
149     :cfunction:`poll()`\ ed for read and write events.
151 Thus, the set of channel events is larger than the basic socket events.
152 The full set of methods that can be overridden in your subclass follows:
154 .. methoddesc:: handle_read()
156     Called when the asynchronous loop detects that a :method:`read()`
157     call on the channel's socket will succeed.
159 .. methoddesc:: handle_write()
161     Called when the asynchronous loop detects that a writable socket
162     can be written.  
163     Often this method will implement the necessary buffering for 
164     performance.  For example::
167         def handle_write(self):
168             sent = self.send(self.buffer)
169             self.buffer = self.buffer[sent:]
171 .. methoddesc:: handle_expt()
173   Called when there is out of band (OOB) data for a socket 
174   connection.  This will almost never happen, as OOB is 
175   tenuously supported and rarely used.
177 .. methoddesc:: handle_connect()
179   Called when the active opener's socket actually makes a connection.
180   Might send a "welcome" banner, or initiate a protocol
181   negotiation with the remote endpoint, for example.
183 .. methoddesc:: handle_close()
185   Called when the socket is closed.
187 .. methoddesc:: handle_error()
189   Called when an exception is raised and not otherwise handled.  The default
190   version prints a condensed traceback.
192 .. methoddesc:: handle_accept()
194   Called on listening channels (passive openers) when a  
195   connection can be established with a new remote endpoint that
196   has issued a :method:`connect()` call for the local endpoint.
198 .. methoddesc:: readable()
200   Called each time around the asynchronous loop to determine whether a
201   channel's socket should be added to the list on which read events can
202   occur.  The default method simply returns ``True``, 
203   indicating that by default, all channels will be interested in
204   read events.
206 .. methoddesc:: writable()
208   Called each time around the asynchronous loop to determine whether a
209   channel's socket should be added to the list on which write events can
210   occur.  The default method simply returns ``True``, 
211   indicating that by default, all channels will be interested in
212   write events.
214 In addition, each channel delegates or extends many of the socket methods.
215 Most of these are nearly identical to their socket partners.
217 .. methoddesc:: create_socket(family, type)
219   This is identical to the creation of a normal socket, and 
220   will use the same options for creation.  Refer to the
221   :refmodule:`socket` documentation for information on creating
222   sockets.
224 .. methoddesc:: connect(address)
226   As with the normal socket object, :var:`address` is a 
227   tuple with the first element the host to connect to, and the 
228   second the port number.
230 .. methoddesc:: send(data)
232   Send :var:`data` to the remote end-point of the socket.
234 .. methoddesc:: recv(buffer_size)
236   Read at most :var:`buffer_size` bytes from the socket's remote end-point.
237   An empty string implies that the channel has been closed from the other
238   end.
240 .. methoddesc:: listen(backlog)
242   Listen for connections made to the socket.  The :var:`backlog`
243   argument specifies the maximum number of queued connections
244   and should be at least 1; the maximum value is
245   system-dependent (usually 5).
247 .. methoddesc:: bind(address)
249   Bind the socket to :var:`address`.  The socket must not already
250   be bound.  (The format of :var:`address` depends on the address
251   family --- see above.)
253 .. methoddesc:: accept()
255   Accept a connection.  The socket must be bound to an address
256   and listening for connections.  The return value is a pair
257   ``(conn , address)`` where :var:`conn` is a
258   *new* socket object usable to send and receive data on
259   the connection, and :var:`address` is the address bound to the
260   socket on the other end of the connection.
262 .. methoddesc:: close()
264   Close the socket.  All future operations on the socket object
265   will fail.  The remote end-point will receive no more data (after
266   queued data is flushed).  Sockets are automatically closed
267   when they are garbage-collected.
270 asyncore Example basic HTTP client :label:`asyncore-example`
271 ------------------------------------------------------------
272 As a basic example, below is a very basic HTTP client that uses the 
273 :class:`dispatcher` class to implement its socket handling::
275         class http_client(asyncore.dispatcher):
276             def __init__(self, host,path):
277                 asyncore.dispatcher.__init__(self)
278                 self.path = path
279                 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
280                 self.connect( (host, 80) )
281                 self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % self.path
283             def handle_connect(self):
284                 pass
286             def handle_read(self):
287                 data = self.recv(8192)
288                 print data
290             def writable(self):
291                 return (len(self.buffer) > 0)
293             def handle_write(self):
294                 sent = self.send(self.buffer)
295                 self.buffer = self.buffer[sent:]