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"?>
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">
7
<title>Twisted Documentation: Writing Clients</title>
8
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
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>
17
<h2>Overview<a name="auto0"/></h2>
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>
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>
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
41
<h2>Protocol<a name="auto1"/></h2>
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>
48
<p>Here is a simple example:</p>
50
<pre class="python"><p class="py-linenumber">1
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>
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
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>
69
<pre class="python"><p class="py-linenumber">1
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>
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">"Hello server, I am the client!\r\n"</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
83
<p>This protocol connects to the server, sends it a welcome message, and
84
then terminates the connection.</p>
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>
91
<h2>Simple, single-use clients<a name="auto2"/></h2>
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
98
<pre class="python"><p class="py-linenumber"> 1
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>
49
115
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Greeter</span>(<span class="py-src-parameter">Protocol</span>):
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">"localhost"</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
128
<h2>ClientFactory<a name="auto3"/></h2>
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>
137
<pre class="python"><p class="py-linenumber"> 1
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>
69
160
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">Protocol</span>):
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>
179
<p>To connect this EchoClientFactory to a server, you could use this
182
<pre class="python"><p class="py-linenumber">1
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
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>
194
<h3>Reconnection<a name="auto4"/></h3>
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>
202
<pre class="python"><p class="py-linenumber">1
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>
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
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>
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.
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>
229
<pre class="python"><p class="py-linenumber"> 1
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>
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>
281
<h2>A Higher-Level Example: ircLogBot<a name="auto5"/></h2>
283
<h3>Overview of ircLogBot<a name="auto6"/></h3>
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>
288
<div class="py-listing"><pre><p class="py-linenumber"> 1
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>
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>
149
429
<span class="py-src-keyword">class</span> <span class="py-src-identifier">MessageLogger</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">"<%s> %s"</span> % (<span class="py-src-variable">user</span>, <span class="py-src-variable">msg</span>))
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">"It isn't nice to whisper! Play nice with the group."</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>
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">":"</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">":"</span>):
208
488
<span class="py-src-variable">msg</span> = <span class="py-src-string">"%s: I am a log bot"</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">"<%s> %s"</span> % (<span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>, <span class="py-src-variable">msg</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">"%s is now known as %s"</span> % (<span class="py-src-variable">old_nick</span>, <span class="py-src-variable">new_nick</span>))
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">"""
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
"""</span>
513
<span class="py-src-keyword">return</span> <span class="py-src-variable">nickname</span> + <span class="py-src-string">'^'</span>
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">"""A factory for LogBots.
229
520
A new protocol instance will be created each time we connect to the server.
230
521
"""</span>
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>
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>
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>)
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>])
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">"irc.freenode.net"</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">f</span>)
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>)
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>])
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">"irc.freenode.net"</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">f</span>)
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>
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>
558
<h3>Persistent Data in the Factory<a name="auto7"/></h3>
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>
565
<pre class="python"><p class="py-linenumber"> 1
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>
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
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>
616
<h2>Further Reading<a name="auto8"/></h2>
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.
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>
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.
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>
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>
636
<p><a href="index.html">Index</a></p>
637
<span class="version">Version: 9.0.0</span>
b'\\ No newline at end of file'