Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 1 | \section{\module{asyncore} --- |
Fred Drake | 38e5d27 | 2000-04-03 20:13:55 +0000 | [diff] [blame] | 2 | Asynchronous socket handler} |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 3 | |
| 4 | \declaremodule{builtin}{asyncore} |
Fred Drake | 38e5d27 | 2000-04-03 20:13:55 +0000 | [diff] [blame] | 5 | \modulesynopsis{A base class for developing asynchronous socket |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 6 | handling services.} |
| 7 | \moduleauthor{Sam Rushing}{rushing@nightmare.com} |
| 8 | \sectionauthor{Christopher Petrilli}{petrilli@amber.org} |
| 9 | % Heavily adapted from original documentation by Sam Rushing. |
| 10 | |
Fred Drake | 38e5d27 | 2000-04-03 20:13:55 +0000 | [diff] [blame] | 11 | This module provides the basic infrastructure for writing asynchronous |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 12 | socket service clients and servers. |
| 13 | |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 14 | There are only two ways to have a program on a single processor do |
| 15 | ``more than one thing at a time.'' Multi-threaded programming is the |
| 16 | simplest and most popular way to do it, but there is another very |
Fred Drake | 6166b87 | 1999-07-06 21:00:18 +0000 | [diff] [blame] | 17 | different technique, that lets you have nearly all the advantages of |
Fred Drake | d5dfe98 | 1999-07-06 15:50:23 +0000 | [diff] [blame] | 18 | multi-threading, without actually using multiple threads. It's really |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 19 | only practical if your program is largely I/O bound. If your program |
Fred Drake | d5dfe98 | 1999-07-06 15:50:23 +0000 | [diff] [blame] | 20 | is CPU bound, then pre-emptive scheduled threads are probably what |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 21 | you really need. Network servers are rarely CPU-bound, however. |
| 22 | |
| 23 | If your operating system supports the \cfunction{select()} system call |
| 24 | in its I/O library (and nearly all do), then you can use it to juggle |
| 25 | multiple communication channels at once; doing other work while your |
| 26 | I/O is taking place in the ``background.'' Although this strategy can |
| 27 | seem strange and complex, especially at first, it is in many ways |
| 28 | easier to understand and control than multi-threaded programming. |
Fred Drake | d5dfe98 | 1999-07-06 15:50:23 +0000 | [diff] [blame] | 29 | The module documented here solves many of the difficult problems for |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 30 | you, making the task of building sophisticated high-performance |
| 31 | network servers and clients a snap. |
| 32 | |
| 33 | \begin{classdesc}{dispatcher}{} |
| 34 | The first class we will introduce is the \class{dispatcher} class. |
| 35 | This is a thin wrapper around a low-level socket object. To make |
| 36 | it more useful, it has a few methods for event-handling on it. |
| 37 | Otherwise, it can be treated as a normal non-blocking socket object. |
| 38 | |
| 39 | The direct interface between the select loop and the socket object |
| 40 | are the \method{handle_read_event()} and |
| 41 | \method{handle_write_event()} methods. These are called whenever an |
| 42 | object `fires' that event. |
| 43 | |
| 44 | The firing of these low-level events can tell us whether certain |
| 45 | higher-level events have taken place, depending on the timing and |
| 46 | the state of the connection. For example, if we have asked for a |
| 47 | socket to connect to another host, we know that the connection has |
| 48 | been made when the socket fires a write event (at this point you |
| 49 | know that you may write to it with the expectation of success). |
| 50 | The implied higher-level events are: |
| 51 | |
| 52 | \begin{tableii}{l|l}{code}{Event}{Description} |
| 53 | \lineii{handle_connect()}{Implied by a write event} |
| 54 | \lineii{handle_close()}{Implied by a read event with no data available} |
| 55 | \lineii{handle_accept()}{Implied by a read event on a listening socket} |
| 56 | \end{tableii} |
| 57 | \end{classdesc} |
| 58 | |
| 59 | This set of user-level events is larger than the basics. The |
| 60 | full set of methods that can be overridden in your subclass are: |
| 61 | |
| 62 | \begin{methoddesc}{handle_read}{} |
| 63 | Called when there is new data to be read from a socket. |
| 64 | \end{methoddesc} |
| 65 | |
| 66 | \begin{methoddesc}{handle_write}{} |
| 67 | Called when there is an attempt to write data to the object. |
| 68 | Often this method will implement the necessary buffering for |
| 69 | performance. For example: |
| 70 | |
| 71 | \begin{verbatim} |
| 72 | def handle_write(self): |
| 73 | sent = self.send(self.buffer) |
| 74 | self.buffer = self.buffer[sent:] |
| 75 | \end{verbatim} |
| 76 | \end{methoddesc} |
| 77 | |
| 78 | \begin{methoddesc}{handle_expt}{} |
| 79 | Called when there is out of band (OOB) data for a socket |
| 80 | connection. This will almost never happen, as OOB is |
| 81 | tenuously supported and rarely used. |
| 82 | \end{methoddesc} |
| 83 | |
| 84 | \begin{methoddesc}{handle_connect}{} |
| 85 | Called when the socket actually makes a connection. This |
| 86 | might be used to send a ``welcome'' banner, or something |
| 87 | similar. |
| 88 | \end{methoddesc} |
| 89 | |
| 90 | \begin{methoddesc}{handle_close}{} |
| 91 | Called when the socket is closed. |
| 92 | \end{methoddesc} |
| 93 | |
| 94 | \begin{methoddesc}{handle_accept}{} |
| 95 | Called on listening sockets when they actually accept a new |
| 96 | connection. |
| 97 | \end{methoddesc} |
| 98 | |
| 99 | \begin{methoddesc}{readable}{} |
| 100 | Each time through the \method{select()} loop, the set of sockets |
| 101 | is scanned, and this method is called to see if there is any |
| 102 | interest in reading. The default method simply returns \code{1}, |
| 103 | indicating that by default, all channels will be interested. |
| 104 | \end{methoddesc} |
| 105 | |
| 106 | \begin{methoddesc}{writeable}{} |
| 107 | Each time through the \method{select()} loop, the set of sockets |
| 108 | is scanned, and this method is called to see if there is any |
| 109 | interest in writing. The default method simply returns \code{1}, |
| 110 | indiciating that by default, all channels will be interested. |
| 111 | \end{methoddesc} |
| 112 | |
| 113 | In addition, there are the basic methods needed to construct and |
| 114 | manipulate ``channels,'' which are what we will call the socket |
| 115 | connections in this context. Note that most of these are nearly |
Fred Drake | d5dfe98 | 1999-07-06 15:50:23 +0000 | [diff] [blame] | 116 | identical to their socket partners. |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 117 | |
| 118 | \begin{methoddesc}{create_socket}{family, type} |
| 119 | This is identical to the creation of a normal socket, and |
Fred Drake | d5dfe98 | 1999-07-06 15:50:23 +0000 | [diff] [blame] | 120 | will use the same options for creation. Refer to the |
| 121 | \refmodule{socket} documentation for information on creating |
| 122 | sockets. |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 123 | \end{methoddesc} |
| 124 | |
| 125 | \begin{methoddesc}{connect}{address} |
Fred Drake | d5dfe98 | 1999-07-06 15:50:23 +0000 | [diff] [blame] | 126 | As with the normal socket object, \var{address} is a |
Fred Drake | 7d80779 | 1999-07-02 14:25:03 +0000 | [diff] [blame] | 127 | tuple with the first element the host to connect to, and the |
| 128 | second the port. |
| 129 | \end{methoddesc} |
| 130 | |
| 131 | \begin{methoddesc}{send}{data} |
| 132 | Send \var{data} out the socket. |
| 133 | \end{methoddesc} |
| 134 | |
| 135 | \begin{methoddesc}{recv}{buffer_size} |
| 136 | Read at most \var{buffer_size} bytes from the socket. |
| 137 | \end{methoddesc} |
| 138 | |
| 139 | \begin{methoddesc}{listen}{\optional{backlog}} |
| 140 | Listen for connections made to the socket. The \var{backlog} |
| 141 | argument specifies the maximum number of queued connections |
| 142 | and should be at least 1; the maximum value is |
| 143 | system-dependent (usually 5). |
| 144 | \end{methoddesc} |
| 145 | |
| 146 | \begin{methoddesc}{bind}{address} |
| 147 | Bind the socket to \var{address}. The socket must not already |
| 148 | be bound. (The format of \var{address} depends on the address |
| 149 | family --- see above.) |
| 150 | \end{methoddesc} |
| 151 | |
| 152 | \begin{methoddesc}{accept}{} |
| 153 | Accept a connection. The socket must be bound to an address |
| 154 | and listening for connections. The return value is a pair |
| 155 | \code{(\var{conn}, \var{address})} where \var{conn} is a |
| 156 | \emph{new} socket object usable to send and receive data on |
| 157 | the connection, and \var{address} is the address bound to the |
| 158 | socket on the other end of the connection. |
| 159 | \end{methoddesc} |
| 160 | |
| 161 | \begin{methoddesc}{close}{} |
| 162 | Close the socket. All future operations on the socket object |
| 163 | will fail. The remote end will receive no more data (after |
| 164 | queued data is flushed). Sockets are automatically closed |
| 165 | when they are garbage-collected. |
| 166 | \end{methoddesc} |
| 167 | |
| 168 | |
| 169 | \subsection{Example basic HTTP client \label{asyncore-example}} |
| 170 | |
| 171 | As a basic example, below is a very basic HTTP client that uses the |
| 172 | \class{dispatcher} class to implement its socket handling: |
| 173 | |
| 174 | \begin{verbatim} |
| 175 | class http_client(asyncore.dispatcher): |
| 176 | def __init__(self, host,path): |
| 177 | asyncore.dispatcher.__init__(self) |
| 178 | self.path = path |
| 179 | self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
| 180 | self.connect( (host, 80) ) |
| 181 | self.buffer = 'GET %s HTTP/1.0\r\b\r\n' % self.path |
| 182 | |
| 183 | def handle_connect(self): |
| 184 | pass |
| 185 | |
| 186 | def handle_read(self): |
| 187 | data = self.recv(8192) |
| 188 | print data |
| 189 | |
| 190 | def writeable(self): |
| 191 | return (len(self.buffer) > 0) |
| 192 | |
| 193 | def handle_write(self): |
| 194 | sent = self.send(self.buffer) |
| 195 | self.buffer = self.buffer[sent:] |
| 196 | \end{verbatim} |