1 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
3 <title>Twisted Documentation: UDP Networking</title>
4 <link href="stylesheet.css" rel="stylesheet" type="text/css"/>
8 <h1 class="title">UDP Networking</h1>
9 <div class="toc"><ol><li><a href="#auto0">Overview</a></li><li><a href="#auto1">DatagramProtocol</a></li><li><a href="#auto2">Connected UDP</a></li><li><a href="#auto3">Multicast UDP</a></li></ol></div>
13 <h2>Overview<a name="auto0"/></h2>
15 <p>Unlike TCP, UDP has no notion of connections. A UDP socket can receive
16 datagrams from any server on the network and send datagrams to any host on
17 the network. In addition, datagrams may arrive in any order, never arrive at
18 all, or be duplicated in transit.</p>
20 <p>Since there are no connections, we only use a single object, a protocol,
21 for each UDP socket. We then use the reactor to connect this protocol to a
22 UDP transport, using the
23 <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IReactorUDP.html" title="twisted.internet.interfaces.IReactorUDP">twisted.internet.interfaces.IReactorUDP</a></code>
26 <h2>DatagramProtocol<a name="auto1"/></h2>
28 <p>The class where you actually implement the protocol parsing and handling
29 will usually be descended
30 from <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.protocol.DatagramProtocol.html" title="twisted.internet.protocol.DatagramProtocol">twisted.internet.protocol.DatagramProtocol</a></code> or
31 from one of its convenience children. The <code>DatagramProtocol</code>
32 class receives datagrams and can send them out over the network. Received
33 datagrams include the address they were sent from. When sending datagrams
34 the destination address must be specified.</p>
36 <p>Here is a simple example:</p>
37 <pre class="python"><p class="py-linenumber"> 1
48 </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">DatagramProtocol</span>
49 <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>
51 <span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span>(<span class="py-src-parameter">DatagramProtocol</span>):
53 <span class="py-src-keyword">def</span> <span class="py-src-identifier">datagramReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>, (<span class="py-src-parameter">host</span>, <span class="py-src-parameter">port</span>)):
54 <span class="py-src-keyword">print</span> <span class="py-src-string">"received %r from %s:%d"</span> % (<span class="py-src-variable">data</span>, <span class="py-src-variable">host</span>, <span class="py-src-variable">port</span>)
55 <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-variable">data</span>, (<span class="py-src-variable">host</span>, <span class="py-src-variable">port</span>))
57 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenUDP</span>(<span class="py-src-number">9999</span>, <span class="py-src-variable">Echo</span>())
58 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
61 <p>As you can see, the protocol is registered with the reactor. This means
62 it may be persisted if it's added to an application, and thus it has
63 <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.protocol.AbstractDatagramProtocol.startProtocol.html" title="twisted.internet.protocol.AbstractDatagramProtocol.startProtocol">startProtocol</a></code>
64 and <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.protocol.AbstractDatagramProtocol.stopProtocol.html" title="twisted.internet.protocol.AbstractDatagramProtocol.stopProtocol">stopProtocol</a></code>
65 methods that will get called when the protocol is connected and disconnected
66 from a UDP socket.</p>
68 <p>The protocol's <code class="python">transport</code> attribute will
69 implement the <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IUDPTransport.html" title="twisted.internet.interfaces.IUDPTransport">twisted.internet.interfaces.IUDPTransport</a></code> interface.
70 Notice that the <code class="python">host</code> argument should be an
71 IP address, not a hostname. If you only have the hostname use <code class="python">reactor.resolve()</code> to resolve the address (see <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IReactorCore.resolve.html" title="twisted.internet.interfaces.IReactorCore.resolve">twisted.internet.interfaces.IReactorCore.resolve</a></code>).</p>
74 <h2>Connected UDP<a name="auto2"/></h2>
76 <p>A connected UDP socket is slightly different from a standard one - it
77 can only send and receive datagrams to/from a single address, but this
78 does not in any way imply a connection. Datagrams may still arrive in any
79 order, and the port on the other side may have no one listening. The
80 benefit of the connected UDP socket is that it it <strong>may</strong>
81 provide notification of undelivered packages. This depends on many
82 factors, almost all of which are out of the control of the application,
83 but it still presents certain benefits which occasionally make it
86 <p>Unlike a regular UDP protocol, we do not need to specify where to send
87 datagrams and are not told where they came from since they can only come
88 from the address to which the socket is 'connected'.</p>
90 <pre class="python"><p class="py-linenumber"> 1
114 </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">DatagramProtocol</span>
115 <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>
117 <span class="py-src-keyword">class</span> <span class="py-src-identifier">Helloer</span>(<span class="py-src-parameter">DatagramProtocol</span>):
119 <span class="py-src-keyword">def</span> <span class="py-src-identifier">startProtocol</span>(<span class="py-src-parameter">self</span>):
120 <span class="py-src-variable">host</span> = <span class="py-src-string">"192.168.1.1"</span>
121 <span class="py-src-variable">port</span> = <span class="py-src-number">1234</span>
123 <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">connect</span>(<span class="py-src-variable">host</span>, <span class="py-src-variable">port</span>)
124 <span class="py-src-keyword">print</span> <span class="py-src-string">"now we can only send to host %s port %d"</span> % (<span class="py-src-variable">host</span>, <span class="py-src-variable">port</span>)
125 <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"</span>) <span class="py-src-comment"># no need for address</span>
127 <span class="py-src-keyword">def</span> <span class="py-src-identifier">datagramReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">data</span>, (<span class="py-src-parameter">host</span>, <span class="py-src-parameter">port</span>)):
128 <span class="py-src-keyword">print</span> <span class="py-src-string">"received %r from %s:%d"</span> % (<span class="py-src-variable">data</span>, <span class="py-src-variable">host</span>, <span class="py-src-variable">port</span>)
130 <span class="py-src-comment"># Possibly invoked if there is no server listening on the</span>
131 <span class="py-src-comment"># address to which we are sending.</span>
132 <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionRefused</span>(<span class="py-src-parameter">self</span>):
133 <span class="py-src-keyword">print</span> <span class="py-src-string">"No one listening"</span>
135 <span class="py-src-comment"># 0 means any port, we don't care in this case</span>
136 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenUDP</span>(<span class="py-src-number">0</span>, <span class="py-src-variable">Helloer</span>())
137 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
140 <p>Note that <code class="python">connect()</code>,
141 like <code class="python">write()</code> will only accept IP addresses, not
142 unresolved hostnames. To obtain the IP of a hostname
143 use <code class="python">reactor.resolve()</code>, e.g.:</p>
145 <pre class="python"><p class="py-linenumber">1
153 </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>
155 <span class="py-src-keyword">def</span> <span class="py-src-identifier">gotIP</span>(<span class="py-src-parameter">ip</span>):
156 <span class="py-src-keyword">print</span> <span class="py-src-string">"IP of 'example.com' is"</span>, <span class="py-src-variable">ip</span>
157 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">3</span>, <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>)
159 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">resolve</span>(<span class="py-src-string">'example.com'</span>).<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">gotIP</span>)
160 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
163 <p>Connecting to a new address after a previous connection or making a
164 connected port unconnected are not currently supported, but likely will be
167 <h2>Multicast UDP<a name="auto3"/></h2>
169 <p>Multicast allows a process to contact multiple hosts with a single
170 packet, without knowing the specific IP address of any of the hosts. This
171 is in contrast to normal, or unicast, UDP, where each datagram has a single
172 IP as its destination. Multicast datagrams are sent to special multicast
173 group addresses (in the IPv4 range 224.0.0.0 to 239.255.255.255), along with
174 a corresponding port. In order to receive multicast datagrams, you must
175 join that specific group address. However, any UDP socket can send to
176 multicast addresses.</p>
178 <div class="py-listing"><pre><p class="py-linenumber"> 1
206 </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">DatagramProtocol</span>
207 <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>
210 <span class="py-src-keyword">class</span> <span class="py-src-identifier">MulticastPingPong</span>(<span class="py-src-parameter">DatagramProtocol</span>):
212 <span class="py-src-keyword">def</span> <span class="py-src-identifier">startProtocol</span>(<span class="py-src-parameter">self</span>):
213 <span class="py-src-string">"""
214 Called after protocol has started listening.
215 """</span>
216 <span class="py-src-comment"># Set the TTL>1 so multicast will cross router hops:</span>
217 <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">setTTL</span>(<span class="py-src-number">5</span>)
218 <span class="py-src-comment"># Join a specific multicast group:</span>
219 <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">joinGroup</span>(<span class="py-src-string">"228.0.0.5"</span>)
221 <span class="py-src-keyword">def</span> <span class="py-src-identifier">datagramReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">datagram</span>, <span class="py-src-parameter">address</span>):
222 <span class="py-src-keyword">print</span> <span class="py-src-string">"Datagram %s received from %s"</span> % (<span class="py-src-variable">repr</span>(<span class="py-src-variable">datagram</span>), <span class="py-src-variable">repr</span>(<span class="py-src-variable">address</span>))
223 <span class="py-src-keyword">if</span> <span class="py-src-variable">datagram</span> == <span class="py-src-string">"Client: Ping"</span>:
224 <span class="py-src-comment"># Rather than replying to the group multicast address, we send the</span>
225 <span class="py-src-comment"># reply directly (unicast) to the originating port:</span>
226 <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">"Server: Pong"</span>, <span class="py-src-variable">address</span>)
229 <span class="py-src-comment"># We use listenMultiple=True so that we can run MulticastServer.py and</span>
230 <span class="py-src-comment"># MulticastClient.py on same machine:</span>
231 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenMulticast</span>(<span class="py-src-number">8005</span>, <span class="py-src-variable">MulticastPingPong</span>(),
232 <span class="py-src-variable">listenMultiple</span>=<span class="py-src-variable">True</span>)
233 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
234 </pre><div class="caption">Source listing - <a href="listings/udp/MulticastServer.py"><span class="filename">listings/udp/MulticastServer.py</span></a></div></div>
236 <p>As with UDP, with multicast there is no server/client differentiation
237 at the protocol level. Our server example is very simple and closely
238 resembles a normal <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IReactorUDP.listenUDP.html" title="twisted.internet.interfaces.IReactorUDP.listenUDP">listenUDP</a></code>
239 protocol implementation. The main difference is that instead
240 of <code>listenUDP</code>, <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IReactorMulticast.listenMulticast.html" title="twisted.internet.interfaces.IReactorMulticast.listenMulticast">listenMulticast</a></code>
241 is called with the port number. The server calls <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IMulticastTransport.joinGroup.html" title="twisted.internet.interfaces.IMulticastTransport.joinGroup">joinGroup</a></code> to
242 join a multicast group. A <code class="python">DatagramProtocol</code>
243 that is listening with multicast and has joined a group can receive
244 multicast datagrams, but also unicast datagrams sent directly to its
245 address. The server in the example above sends such a unicast message in
246 reply to the multicast message it receives from the client.
249 <div class="py-listing"><pre><p class="py-linenumber"> 1
268 </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">DatagramProtocol</span>
269 <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>
272 <span class="py-src-keyword">class</span> <span class="py-src-identifier">MulticastPingClient</span>(<span class="py-src-parameter">DatagramProtocol</span>):
274 <span class="py-src-keyword">def</span> <span class="py-src-identifier">startProtocol</span>(<span class="py-src-parameter">self</span>):
275 <span class="py-src-comment"># Join the multicast address, so we can receive replies:</span>
276 <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">joinGroup</span>(<span class="py-src-string">"228.0.0.5"</span>)
277 <span class="py-src-comment"># Send to 228.0.0.5:8005 - all listeners on the multicast address</span>
278 <span class="py-src-comment"># (including us) will receive this message.</span>
279 <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">'Client: Ping'</span>, (<span class="py-src-string">"228.0.0.5"</span>, <span class="py-src-number">8005</span>))
281 <span class="py-src-keyword">def</span> <span class="py-src-identifier">datagramReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">datagram</span>, <span class="py-src-parameter">address</span>):
282 <span class="py-src-keyword">print</span> <span class="py-src-string">"Datagram %s received from %s"</span> % (<span class="py-src-variable">repr</span>(<span class="py-src-variable">datagram</span>), <span class="py-src-variable">repr</span>(<span class="py-src-variable">address</span>))
285 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenMulticast</span>(<span class="py-src-number">8005</span>, <span class="py-src-variable">MulticastPingClient</span>(), <span class="py-src-variable">listenMultiple</span>=<span class="py-src-variable">True</span>)
286 <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
287 </pre><div class="caption">Source listing - <a href="listings/udp/MulticastClient.py"><span class="filename">listings/udp/MulticastClient.py</span></a></div></div>
289 <p>Note that a multicast socket will have a default TTL (time to live) of
290 1. That is, datagrams won't traverse more than one router hop, unless a
291 higher TTL is set with
292 <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IMulticastTransport.setTTL.html" title="twisted.internet.interfaces.IMulticastTransport.setTTL">setTTL</a></code>. Other
293 functionality provided by the multicast transport
294 includes <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IMulticastTransport.setOutgoingInterface.html" title="twisted.internet.interfaces.IMulticastTransport.setOutgoingInterface">setOutgoingInterface</a></code>
295 and <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IMulticastTransport.setLoopbackMode.html" title="twisted.internet.interfaces.IMulticastTransport.setLoopbackMode">setLoopbackMode</a></code>
296 -- see <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.internet.interfaces.IMulticastTransport.html" title="twisted.internet.interfaces.IMulticastTransport">IMulticastTransport</a></code> for more
301 <p><a href="index.html">Index</a></p>
302 <span class="version">Version: 12.1.0</span>