~certify-web-dev/twisted/certify-staging

« back to all changes in this revision

Viewing changes to doc/howto/clients.html

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-01-02 19:38:17 UTC
  • mfrom: (2.2.4 sid)
  • Revision ID: james.westby@ubuntu.com-20100102193817-jphp464ppwh7dulg
Tags: 9.0.0-1
* python-twisted: Depend on the python-twisted-* 9.0 packages.
* python-twisted: Depend on python-zope.interface only. Closes: #557781.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Writing Clients</title><link href="stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Writing Clients</h1><div class="toc"><ol><li><a href="#auto0">Overview</a></li><li><a href="#auto1">Protocol</a></li><li><a href="#auto2">Simple, single-use clients</a></li><li><a href="#auto3">ClientFactory</a></li><ul><li><a href="#auto4">Reconnection</a></li></ul><li><a href="#auto5">A Higher-Level Example: ircLogBot</a></li><ul><li><a href="#auto6">Overview of ircLogBot</a></li><li><a href="#auto7">Persistent Data in the Factory</a></li></ul><li><a href="#auto8">Further Reading</a></li></ol></div><div class="content"><span></span><h2>Overview<a name="auto0"></a></h2><p>Twisted is a framework designed to be very flexible, and let you write
 
1
<?xml version="1.0" encoding="utf-8"?>
 
2
<!DOCTYPE html
 
3
  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
 
4
  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
 
5
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
 
6
  <head>
 
7
<title>Twisted Documentation: Writing Clients</title>
 
8
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
 
9
  </head>
 
10
 
 
11
  <body bgcolor="white">
 
12
    <h1 class="title">Writing Clients</h1>
 
13
    <div class="toc"><ol><li><a href="#auto0">Overview</a></li><li><a href="#auto1">Protocol</a></li><li><a href="#auto2">Simple, single-use clients</a></li><li><a href="#auto3">ClientFactory</a></li><ul><li><a href="#auto4">Reconnection</a></li></ul><li><a href="#auto5">A Higher-Level Example: ircLogBot</a></li><ul><li><a href="#auto6">Overview of ircLogBot</a></li><li><a href="#auto7">Persistent Data in the Factory</a></li></ul><li><a href="#auto8">Further Reading</a></li></ol></div>
 
14
    <div class="content">
 
15
    <span/>
 
16
    
 
17
    <h2>Overview<a name="auto0"/></h2>
 
18
 
 
19
    <p>Twisted is a framework designed to be very flexible, and let you write
3
20
    powerful clients. The cost of this flexibility is a few layers in the way
4
21
    to writing your client. This document covers creating clients that can be
5
 
    used for TCP, SSL and Unix sockets, UDP is covered <a href="udp.html">in
6
 
    a different document</a>.</p><p>At the base, the place where you actually implement the protocol parsing
 
22
    used for TCP, SSL and Unix sockets, UDP is covered <a href="udp.html" shape="rect">in
 
23
    a different document</a>.</p>
 
24
    
 
25
    <p>At the base, the place where you actually implement the protocol parsing
7
26
    and handling, is the Protocol class. This class will usually be decended
8
 
    from <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.Protocol.html" title="twisted.internet.protocol.Protocol">twisted.internet.protocol.Protocol</a></code>. Most
 
27
    from <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.Protocol.html" title="twisted.internet.protocol.Protocol">twisted.internet.protocol.Protocol</a></code>. Most
9
28
    protocol handlers inherit either from this class or from one of its
10
29
    convenience children. An instance of the protocol class will be
11
30
    instantiated when you connect to the server, and will go away when the
12
31
    connection is finished.  This means that persistent configuration is not
13
 
    saved in the Protocol.</p><p>The persistent configuration is kept in a Factory class, which usually
14
 
    inherits from <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.ClientFactory.html" title="twisted.internet.protocol.ClientFactory">twisted.internet.protocol.ClientFactory</a></code>. The default
 
32
    saved in the Protocol.</p>
 
33
    
 
34
    <p>The persistent configuration is kept in a Factory class, which usually
 
35
    inherits from <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.ClientFactory.html" title="twisted.internet.protocol.ClientFactory">twisted.internet.protocol.ClientFactory</a></code>. The default
15
36
    factory class just instantiate the Protocol, and then sets on it an
16
37
    attribute called <code>factory</code> which points to itself. This let
17
38
    the Protocol access, and possibly modify, the persistent
18
 
    configuration.</p><h2>Protocol<a name="auto1"></a></h2><p>As mentioned above, this, and auxiliary classes and functions, is where
 
39
    configuration.</p>
 
40
    
 
41
    <h2>Protocol<a name="auto1"/></h2>
 
42
    
 
43
    <p>As mentioned above, this, and auxiliary classes and functions, is where
19
44
    most of the code is. A Twisted protocol handles data in an asynchronous
20
45
    manner. What this means is that the protocol never waits for an event, but
21
 
    rather responds to events as they arrive from the network.</p><p>Here is a simple example:</p><pre class="python">
22
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>
 
46
    rather responds to events as they arrive from the network.</p>
 
47
    
 
48
    <p>Here is a simple example:</p>
 
49
 
 
50
    <pre class="python"><p class="py-linenumber">1
 
51
2
 
52
3
 
53
4
 
54
5
 
55
6
 
56
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>
23
57
<span class="py-src-keyword">from</span> <span class="py-src-variable">sys</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">stdout</span>
24
58
 
25
59
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">Protocol</span>):
26
60
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">dataReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>):
27
61
        <span class="py-src-variable">stdout</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">data</span>)
28
 
</pre><p>This is one of the simplest protocols.  It simply writes to standard
 
62
</pre>
 
63
    
 
64
    <p>This is one of the simplest protocols.  It simply writes to standard
29
65
    output whatever it reads from the connection.  There are many events it
30
66
    does not respond to.  Here is an example of a Protocol responding to
31
 
    another event.</p><pre class="python">
32
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>
 
67
    another event.</p>
 
68
 
 
69
    <pre class="python"><p class="py-linenumber">1
 
70
2
 
71
3
 
72
4
 
73
5
 
74
6
 
75
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>
33
76
 
34
77
<span class="py-src-keyword">class</span> <span class="py-src-identifier">WelcomeMessage</span>(<span class="py-src-parameter">Protocol</span>):
35
78
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
36
79
        <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">&quot;Hello server, I am the client!\r\n&quot;</span>)
37
80
        <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
38
 
</pre><p>This protocol connects to the server, sends it a welcome message, and
39
 
    then terminates the connection.</p><p>The connectionMade event is usually where set up of the Protocol
 
81
</pre>
 
82
    
 
83
    <p>This protocol connects to the server, sends it a welcome message, and
 
84
    then terminates the connection.</p>
 
85
    
 
86
    <p>The connectionMade event is usually where set up of the Protocol
40
87
    object happens, as well as any initial greetings (as in the
41
88
    WelcomeMessage protocol above). Any tearing down of Protocol-specific
42
 
    objects is done in connectionLost.</p><h2>Simple, single-use clients<a name="auto2"></a></h2><p>In many cases, the protocol only needs to connect to the server once,
 
89
    objects is done in connectionLost.</p>
 
90
 
 
91
    <h2>Simple, single-use clients<a name="auto2"/></h2>
 
92
 
 
93
    <p>In many cases, the protocol only needs to connect to the server once,
43
94
    and the code just wants to get a connected instance of the protocol. In
44
 
    those cases <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.ClientCreator.html" title="twisted.internet.protocol.ClientCreator">twisted.internet.protocol.ClientCreator</a></code> provides the
45
 
    appropriate API.</p><pre class="python">
46
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
 
95
    those cases <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.ClientCreator.html" title="twisted.internet.protocol.ClientCreator">twisted.internet.protocol.ClientCreator</a></code> provides the
 
96
    appropriate API.</p>
 
97
 
 
98
    <pre class="python"><p class="py-linenumber"> 1
 
99
 2
 
100
 3
 
101
 4
 
102
 5
 
103
 6
 
104
 7
 
105
 8
 
106
 9
 
107
10
 
108
11
 
109
12
 
110
13
 
111
14
 
112
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
47
113
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>, <span class="py-src-variable">ClientCreator</span>
48
114
 
49
115
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Greeter</span>(<span class="py-src-parameter">Protocol</span>):
57
123
 
58
124
<span class="py-src-variable">c</span> = <span class="py-src-variable">ClientCreator</span>(<span class="py-src-variable">reactor</span>, <span class="py-src-variable">Greeter</span>)
59
125
<span class="py-src-variable">c</span>.<span class="py-src-variable">connectTCP</span>(<span class="py-src-string">&quot;localhost&quot;</span>, <span class="py-src-number">1234</span>).<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">gotProtocol</span>)
60
 
</pre><h2>ClientFactory<a name="auto3"></a></h2><p>We use reactor.connect* and a ClientFactory. The ClientFactory is in
 
126
</pre>
 
127
                
 
128
    <h2>ClientFactory<a name="auto3"/></h2>
 
129
 
 
130
    <p>We use reactor.connect* and a ClientFactory. The ClientFactory is in
61
131
    charge of creating the Protocol, and also receives events relating to the
62
132
    connection state. This allows it to do things like reconnect on the event
63
133
    of a connection error. Here is an example of a simple ClientFactory that
64
134
    uses the Echo protocol (above) and also prints what state the connection
65
 
    is in.</p><pre class="python">
66
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>, <span class="py-src-variable">ClientFactory</span>
 
135
    is in.</p>
 
136
 
 
137
    <pre class="python"><p class="py-linenumber"> 1
 
138
 2
 
139
 3
 
140
 4
 
141
 5
 
142
 6
 
143
 7
 
144
 8
 
145
 9
 
146
10
 
147
11
 
148
12
 
149
13
 
150
14
 
151
15
 
152
16
 
153
17
 
154
18
 
155
19
 
156
20
 
157
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>, <span class="py-src-variable">ClientFactory</span>
67
158
<span class="py-src-keyword">from</span> <span class="py-src-variable">sys</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">stdout</span>
68
159
 
69
160
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">Protocol</span>):
83
174
    
84
175
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionFailed</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>):
85
176
        <span class="py-src-keyword">print</span> <span class="py-src-string">'Connection failed. Reason:'</span>, <span class="py-src-variable">reason</span>
86
 
</pre><p>To connect this EchoClientFactory to a server, you could use this
87
 
    code:</p><pre class="python">
88
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
 
177
</pre>
 
178
    
 
179
    <p>To connect this EchoClientFactory to a server, you could use this
 
180
    code:</p>
 
181
 
 
182
    <pre class="python"><p class="py-linenumber">1
 
183
2
 
184
3
 
185
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
89
186
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">connectTCP</span>(<span class="py-src-variable">host</span>, <span class="py-src-variable">port</span>, <span class="py-src-variable">EchoClientFactory</span>())
90
187
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
91
 
</pre><p>Note that <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.ClientFactory.clientConnectionFailed.html" title="twisted.internet.protocol.ClientFactory.clientConnectionFailed">clientConnectionFailed</a></code>
92
 
    is called when a connection could not be established, and that <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.ClientFactory.clientConnectionLost.html" title="twisted.internet.protocol.ClientFactory.clientConnectionLost">clientConnectionLost</a></code>
93
 
    is called when a connection was made and then disconnected.</p><h3>Reconnection<a name="auto4"></a></h3><p>Many times, the connection of a client will be lost unintentionally due
 
188
</pre>
 
189
 
 
190
    <p>Note that <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.ClientFactory.clientConnectionFailed.html" title="twisted.internet.protocol.ClientFactory.clientConnectionFailed">clientConnectionFailed</a></code>
 
191
    is called when a connection could not be established, and that <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.ClientFactory.clientConnectionLost.html" title="twisted.internet.protocol.ClientFactory.clientConnectionLost">clientConnectionLost</a></code>
 
192
    is called when a connection was made and then disconnected.</p>
 
193
    
 
194
    <h3>Reconnection<a name="auto4"/></h3>
 
195
 
 
196
    <p>Many times, the connection of a client will be lost unintentionally due
94
197
    to network errors. One way to reconnect after a disconnection would be to
95
198
    call <code class="python">connector.connect()</code> when the
96
199
    connection is lost:
97
 
    </p><pre class="python">
98
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ClientFactory</span>
 
200
    </p>
 
201
 
 
202
    <pre class="python"><p class="py-linenumber">1
 
203
2
 
204
3
 
205
4
 
206
5
 
207
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ClientFactory</span>
99
208
 
100
209
<span class="py-src-keyword">class</span> <span class="py-src-identifier">EchoClientFactory</span>(<span class="py-src-parameter">ClientFactory</span>):
101
210
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">clientConnectionLost</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">connector</span>, <span class="py-src-parameter">reason</span>):
102
211
        <span class="py-src-variable">connector</span>.<span class="py-src-variable">connect</span>()
103
 
</pre><p>The connector passed as the first argument is the interface between a
 
212
</pre>
 
213
 
 
214
    <p>The connector passed as the first argument is the interface between a
104
215
    connection and a protocol. When the connection fails and the factory
105
216
    receives the clientConnectionLost event, the factory can call <code class="python">connector.connect()</code> to start the connection over
106
 
    again from scratch.</p><p>
107
 
    However, most programs that want this functionality should implement <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.ReconnectingClientFactory.html" title="twisted.internet.protocol.ReconnectingClientFactory">ReconnectingClientFactory</a></code> instead,
 
217
    again from scratch.</p>
 
218
 
 
219
    <p>
 
220
    However, most programs that want this functionality should implement <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.ReconnectingClientFactory.html" title="twisted.internet.protocol.ReconnectingClientFactory">ReconnectingClientFactory</a></code> instead,
108
221
    which tries to reconnect if a connection is lost or fails, and which
109
222
    exponentially delays repeated reconnect attempts.
110
 
    </p><p>
 
223
    </p>
 
224
 
 
225
    <p>
111
226
    Here is the Echo protocol implemented with a ReconnectingClientFactory:
112
 
    </p><pre class="python">
113
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>, <span class="py-src-variable">ReconnectingClientFactory</span>
 
227
    </p>
 
228
 
 
229
    <pre class="python"><p class="py-linenumber"> 1
 
230
 2
 
231
 3
 
232
 4
 
233
 5
 
234
 6
 
235
 7
 
236
 8
 
237
 9
 
238
10
 
239
11
 
240
12
 
241
13
 
242
14
 
243
15
 
244
16
 
245
17
 
246
18
 
247
19
 
248
20
 
249
21
 
250
22
 
251
23
 
252
24
 
253
25
 
254
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Protocol</span>, <span class="py-src-variable">ReconnectingClientFactory</span>
114
255
<span class="py-src-keyword">from</span> <span class="py-src-variable">sys</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">stdout</span>
115
256
 
116
257
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">Protocol</span>):
135
276
        <span class="py-src-keyword">print</span> <span class="py-src-string">'Connection failed. Reason:'</span>, <span class="py-src-variable">reason</span>
136
277
        <span class="py-src-variable">ReconnectingClientFactory</span>.<span class="py-src-variable">clientConnectionFailed</span>(<span class="py-src-variable">self</span>, <span class="py-src-variable">connector</span>,
137
278
                                                         <span class="py-src-variable">reason</span>)
138
 
</pre><h2>A Higher-Level Example: ircLogBot<a name="auto5"></a></h2><h3>Overview of ircLogBot<a name="auto6"></a></h3><p>The clients so far have been fairly simple.  A more complicated
139
 
    example comes with Twisted Words in the doc/examples directory.</p><div class="py-listing"><pre>
140
 
<span class="py-src-comment"># twisted imports
141
 
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">words</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span>
 
279
</pre>
 
280
 
 
281
    <h2>A Higher-Level Example: ircLogBot<a name="auto5"/></h2>
 
282
    
 
283
    <h3>Overview of ircLogBot<a name="auto6"/></h3>
 
284
 
 
285
    <p>The clients so far have been fairly simple.  A more complicated
 
286
    example comes with Twisted Words in the doc/examples directory.</p>
 
287
    
 
288
    <div class="py-listing"><pre><p class="py-linenumber">  1
 
289
  2
 
290
  3
 
291
  4
 
292
  5
 
293
  6
 
294
  7
 
295
  8
 
296
  9
 
297
 10
 
298
 11
 
299
 12
 
300
 13
 
301
 14
 
302
 15
 
303
 16
 
304
 17
 
305
 18
 
306
 19
 
307
 20
 
308
 21
 
309
 22
 
310
 23
 
311
 24
 
312
 25
 
313
 26
 
314
 27
 
315
 28
 
316
 29
 
317
 30
 
318
 31
 
319
 32
 
320
 33
 
321
 34
 
322
 35
 
323
 36
 
324
 37
 
325
 38
 
326
 39
 
327
 40
 
328
 41
 
329
 42
 
330
 43
 
331
 44
 
332
 45
 
333
 46
 
334
 47
 
335
 48
 
336
 49
 
337
 50
 
338
 51
 
339
 52
 
340
 53
 
341
 54
 
342
 55
 
343
 56
 
344
 57
 
345
 58
 
346
 59
 
347
 60
 
348
 61
 
349
 62
 
350
 63
 
351
 64
 
352
 65
 
353
 66
 
354
 67
 
355
 68
 
356
 69
 
357
 70
 
358
 71
 
359
 72
 
360
 73
 
361
 74
 
362
 75
 
363
 76
 
364
 77
 
365
 78
 
366
 79
 
367
 80
 
368
 81
 
369
 82
 
370
 83
 
371
 84
 
372
 85
 
373
 86
 
374
 87
 
375
 88
 
376
 89
 
377
 90
 
378
 91
 
379
 92
 
380
 93
 
381
 94
 
382
 95
 
383
 96
 
384
 97
 
385
 98
 
386
 99
 
387
100
 
388
101
 
389
102
 
390
103
 
391
104
 
392
105
 
393
106
 
394
107
 
395
108
 
396
109
 
397
110
 
398
111
 
399
112
 
400
113
 
401
114
 
402
115
 
403
116
 
404
117
 
405
118
 
406
119
 
407
120
 
408
121
 
409
122
 
410
123
 
411
124
 
412
125
 
413
126
 
414
127
 
415
128
 
416
129
 
417
130
 
418
131
 
419
132
 
420
</p><span class="py-src-comment"># twisted imports</span>
 
421
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">words</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span>
142
422
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>, <span class="py-src-variable">protocol</span>
143
423
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">log</span>
144
424
 
145
 
<span class="py-src-comment"># system imports
146
 
</span><span class="py-src-keyword">import</span> <span class="py-src-variable">time</span>, <span class="py-src-variable">sys</span>
 
425
<span class="py-src-comment"># system imports</span>
 
426
<span class="py-src-keyword">import</span> <span class="py-src-variable">time</span>, <span class="py-src-variable">sys</span>
147
427
 
148
428
 
149
429
<span class="py-src-keyword">class</span> <span class="py-src-identifier">MessageLogger</span>:
182
462
        <span class="py-src-variable">self</span>.<span class="py-src-variable">logger</span>.<span class="py-src-variable">close</span>()
183
463
 
184
464
 
185
 
    <span class="py-src-comment"># callbacks for events
186
 
</span>
 
465
    <span class="py-src-comment"># callbacks for events</span>
 
466
 
187
467
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">signedOn</span>(<span class="py-src-parameter">self</span>):
188
468
        <span class="py-src-string">&quot;&quot;&quot;Called when bot has succesfully signed on to server.&quot;&quot;&quot;</span>
189
469
        <span class="py-src-variable">self</span>.<span class="py-src-variable">join</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">channel</span>)
197
477
        <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'!'</span>, <span class="py-src-number">1</span>)[<span class="py-src-number">0</span>]
198
478
        <span class="py-src-variable">self</span>.<span class="py-src-variable">logger</span>.<span class="py-src-variable">log</span>(<span class="py-src-string">&quot;&lt;%s&gt; %s&quot;</span> % (<span class="py-src-variable">user</span>, <span class="py-src-variable">msg</span>))
199
479
 
200
 
        <span class="py-src-comment"># Check to see if they're sending me a private message
201
 
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">channel</span> == <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>:
 
480
        <span class="py-src-comment"># Check to see if they're sending me a private message</span>
 
481
        <span class="py-src-keyword">if</span> <span class="py-src-variable">channel</span> == <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>:
202
482
            <span class="py-src-variable">msg</span> = <span class="py-src-string">&quot;It isn't nice to whisper!  Play nice with the group.&quot;</span>
203
483
            <span class="py-src-variable">self</span>.<span class="py-src-variable">msg</span>(<span class="py-src-variable">user</span>, <span class="py-src-variable">msg</span>)
204
484
            <span class="py-src-keyword">return</span>
205
485
 
206
 
        <span class="py-src-comment"># Otherwise check to see if it is a message directed at me
207
 
</span>        <span class="py-src-keyword">if</span> <span class="py-src-variable">msg</span>.<span class="py-src-variable">startswith</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span> + <span class="py-src-string">&quot;:&quot;</span>):
 
486
        <span class="py-src-comment"># Otherwise check to see if it is a message directed at me</span>
 
487
        <span class="py-src-keyword">if</span> <span class="py-src-variable">msg</span>.<span class="py-src-variable">startswith</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span> + <span class="py-src-string">&quot;:&quot;</span>):
208
488
            <span class="py-src-variable">msg</span> = <span class="py-src-string">&quot;%s: I am a log bot&quot;</span> % <span class="py-src-variable">user</span>
209
489
            <span class="py-src-variable">self</span>.<span class="py-src-variable">msg</span>(<span class="py-src-variable">channel</span>, <span class="py-src-variable">msg</span>)
210
490
            <span class="py-src-variable">self</span>.<span class="py-src-variable">logger</span>.<span class="py-src-variable">log</span>(<span class="py-src-string">&quot;&lt;%s&gt; %s&quot;</span> % (<span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>, <span class="py-src-variable">msg</span>))
214
494
        <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'!'</span>, <span class="py-src-number">1</span>)[<span class="py-src-number">0</span>]
215
495
        <span class="py-src-variable">self</span>.<span class="py-src-variable">logger</span>.<span class="py-src-variable">log</span>(<span class="py-src-string">&quot;* %s %s&quot;</span> % (<span class="py-src-variable">user</span>, <span class="py-src-variable">msg</span>))
216
496
 
217
 
    <span class="py-src-comment"># irc callbacks
218
 
</span>
 
497
    <span class="py-src-comment"># irc callbacks</span>
 
498
 
219
499
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">irc_NICK</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">prefix</span>, <span class="py-src-parameter">params</span>):
220
500
        <span class="py-src-string">&quot;&quot;&quot;Called when an IRC user changes their nickname.&quot;&quot;&quot;</span>
221
501
        <span class="py-src-variable">old_nick</span> = <span class="py-src-variable">prefix</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'!'</span>)[<span class="py-src-number">0</span>]
223
503
        <span class="py-src-variable">self</span>.<span class="py-src-variable">logger</span>.<span class="py-src-variable">log</span>(<span class="py-src-string">&quot;%s is now known as %s&quot;</span> % (<span class="py-src-variable">old_nick</span>, <span class="py-src-variable">new_nick</span>))
224
504
 
225
505
 
 
506
    <span class="py-src-comment"># For fun, override the method that determines how a nickname is changed on</span>
 
507
    <span class="py-src-comment"># collisions. The default method appends an underscore.</span>
 
508
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">alterCollidedNick</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">nickname</span>):
 
509
        <span class="py-src-string">&quot;&quot;&quot;
 
510
        Generate an altered version of a nickname that caused a collision in an
 
511
        effort to create an unused related name for subsequent registration.
 
512
        &quot;&quot;&quot;</span>
 
513
        <span class="py-src-keyword">return</span> <span class="py-src-variable">nickname</span> + <span class="py-src-string">'^'</span>
 
514
 
 
515
 
 
516
 
226
517
<span class="py-src-keyword">class</span> <span class="py-src-identifier">LogBotFactory</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">ClientFactory</span>):
227
518
    <span class="py-src-string">&quot;&quot;&quot;A factory for LogBots.
228
519
 
229
520
    A new protocol instance will be created each time we connect to the server.
230
521
    &quot;&quot;&quot;</span>
231
522
 
232
 
    <span class="py-src-comment"># the class of the protocol to build when new connection is made
233
 
</span>    <span class="py-src-variable">protocol</span> = <span class="py-src-variable">LogBot</span>
 
523
    <span class="py-src-comment"># the class of the protocol to build when new connection is made</span>
 
524
    <span class="py-src-variable">protocol</span> = <span class="py-src-variable">LogBot</span>
234
525
 
235
526
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">channel</span>, <span class="py-src-parameter">filename</span>):
236
527
        <span class="py-src-variable">self</span>.<span class="py-src-variable">channel</span> = <span class="py-src-variable">channel</span>
246
537
 
247
538
 
248
539
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
249
 
    <span class="py-src-comment"># initialize logging
250
 
</span>    <span class="py-src-variable">log</span>.<span class="py-src-variable">startLogging</span>(<span class="py-src-variable">sys</span>.<span class="py-src-variable">stdout</span>)
251
 
 
252
 
    <span class="py-src-comment"># create factory protocol and application
253
 
</span>    <span class="py-src-variable">f</span> = <span class="py-src-variable">LogBotFactory</span>(<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">1</span>], <span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">2</span>])
254
 
 
255
 
    <span class="py-src-comment"># connect factory to this host and port
256
 
</span>    <span class="py-src-variable">reactor</span>.<span class="py-src-variable">connectTCP</span>(<span class="py-src-string">&quot;irc.freenode.net&quot;</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">f</span>)
257
 
 
258
 
    <span class="py-src-comment"># run bot
259
 
</span>    <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
260
 
</pre><div class="caption">Source listing - <a href="../../words/examples/ircLogBot.py"><span class="filename">../../words/examples/ircLogBot.py</span></a></div></div><p>ircLogBot.py connects to an IRC server, joins a channel, and logs all
 
540
    <span class="py-src-comment"># initialize logging</span>
 
541
    <span class="py-src-variable">log</span>.<span class="py-src-variable">startLogging</span>(<span class="py-src-variable">sys</span>.<span class="py-src-variable">stdout</span>)
 
542
 
 
543
    <span class="py-src-comment"># create factory protocol and application</span>
 
544
    <span class="py-src-variable">f</span> = <span class="py-src-variable">LogBotFactory</span>(<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">1</span>], <span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">2</span>])
 
545
 
 
546
    <span class="py-src-comment"># connect factory to this host and port</span>
 
547
    <span class="py-src-variable">reactor</span>.<span class="py-src-variable">connectTCP</span>(<span class="py-src-string">&quot;irc.freenode.net&quot;</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">f</span>)
 
548
 
 
549
    <span class="py-src-comment"># run bot</span>
 
550
    <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
 
551
</pre><div class="caption">Source listing - <a href="../../words/examples/ircLogBot.py"><span class="filename">../../words/examples/ircLogBot.py</span></a></div></div>
 
552
    
 
553
    <p>ircLogBot.py connects to an IRC server, joins a channel, and logs all
261
554
    traffic on it to a file. It demonstrates some of the connection-level
262
555
    logic of reconnecting on a lost connection, as well as storing persistent
263
 
    data in the Factory.</p><h3>Persistent Data in the Factory<a name="auto7"></a></h3><p>Since the Protocol instance is recreated each time the connection is
 
556
    data in the Factory.</p>
 
557
    
 
558
    <h3>Persistent Data in the Factory<a name="auto7"/></h3>
 
559
 
 
560
    <p>Since the Protocol instance is recreated each time the connection is
264
561
    made, the client needs some way to keep track of data that should be
265
562
    persisted.  In the case of the logging bot, it needs to know which channel
266
 
    it is logging, and where to log it to.</p><pre class="python">
267
 
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>
 
563
    it is logging, and where to log it to.</p>
 
564
 
 
565
    <pre class="python"><p class="py-linenumber"> 1
 
566
 2
 
567
 3
 
568
 4
 
569
 5
 
570
 6
 
571
 7
 
572
 8
 
573
 9
 
574
10
 
575
11
 
576
12
 
577
13
 
578
14
 
579
15
 
580
16
 
581
17
 
582
18
 
583
19
 
584
20
 
585
21
 
586
22
 
587
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>
268
588
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span>
269
589
 
270
590
<span class="py-src-keyword">class</span> <span class="py-src-identifier">LogBot</span>(<span class="py-src-parameter">irc</span>.<span class="py-src-parameter">IRCClient</span>):
286
606
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">channel</span>, <span class="py-src-parameter">filename</span>):
287
607
        <span class="py-src-variable">self</span>.<span class="py-src-variable">channel</span> = <span class="py-src-variable">channel</span>
288
608
        <span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span> = <span class="py-src-variable">filename</span>
289
 
</pre><p>When the protocol is created, it gets a reference to the factory as
 
609
</pre>
 
610
    
 
611
    <p>When the protocol is created, it gets a reference to the factory as
290
612
    self.factory. It can then access attributes of the factory in its logic.
291
613
    In the case of LogBot, it opens the file and connects to the channel
292
 
    stored in the factory.</p><h2>Further Reading<a name="auto8"></a></h2><p>The <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.protocol.Protocol.html" title="twisted.internet.protocol.Protocol">Protocol</a></code>
293
 
    class used throughout this document is a base implementation of <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.interfaces.IProtocol.html" title="twisted.internet.interfaces.IProtocol">IProtocol</a></code> used in
 
614
    stored in the factory.</p>
 
615
 
 
616
    <h2>Further Reading<a name="auto8"/></h2>
 
617
 
 
618
    <p>The <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.protocol.Protocol.html" title="twisted.internet.protocol.Protocol">Protocol</a></code>
 
619
    class used throughout this document is a base implementation of <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.interfaces.IProtocol.html" title="twisted.internet.interfaces.IProtocol">IProtocol</a></code> used in
294
620
    most Twisted applications for convenience.  To learn about the
295
621
    complete<code>IProtocol</code> interface, see the API documentation for
296
 
    <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.interfaces.IProtocol.html" title="twisted.internet.interfaces.IProtocol">IProtocol</a></code>.</p><p>The <code>transport</code> attribute used in some examples in this
297
 
    document provides the <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.interfaces.
298
 
    ITCPTransport.html" title="twisted.internet.interfaces.
299
 
    ITCPTransport">
 
622
    <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.interfaces.IProtocol.html" title="twisted.internet.interfaces.IProtocol">IProtocol</a></code>.</p>
 
623
 
 
624
    <p>The <code>transport</code> attribute used in some examples in this
 
625
    document provides the <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.interfaces.
 
626
.html" title="twisted.internet.interfaces.
 
627
">
300
628
    ITCPTransport</a></code> interface.  To learn about the complete interface, see
301
 
    the API documentation for <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.interfaces.ITCPTransport.html" title="twisted.internet.interfaces.ITCPTransport">ITCPTransport</a></code>.</p><p>Interface classes are a way of specifying what methods and attributes an
302
 
    object has and how they behave.  See the <a href="components.html">
303
 
    Components: Interfaces and Adapters</a> document.</p></div><p><a href="index.html">Index</a></p><span class="version">Version: 8.2.0</span></body></html>
 
 
b'\\ No newline at end of file'
 
629
    the API documentation for <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.interfaces.ITCPTransport.html" title="twisted.internet.interfaces.ITCPTransport">ITCPTransport</a></code>.</p>
 
630
 
 
631
    <p>Interface classes are a way of specifying what methods and attributes an
 
632
    object has and how they behave.  See the <a href="components.html" shape="rect">
 
633
    Components: Interfaces and Adapters</a> document.</p>
 
634
  </div>
 
635
 
 
636
    <p><a href="index.html">Index</a></p>
 
637
    <span class="version">Version: 9.0.0</span>
 
638
  </body>
 
639
</html>
 
 
b'\\ No newline at end of file'