udp.html   [plain text]


<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: UDP Networking</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">UDP Networking</h1><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></ol></div><div class="content"><span></span><h2>Overview<a name="auto0"></a></h2><p>Unlike TCP, UDP has no notion of connections. A UDP socket can receive
    datagrams from any server on the network, and send datagrams to any host
    on the network. In addition, datagrams may arrive in any order, never
    arrive at all, or be duplicated in transit.</p><p>Since there are no multiple connections, we only use a single object,
    a protocol, for each UDP socket. We then use the reactor to connect
    this protocol to a UDP transport, using the 
    <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.interfaces.IReactorUDP.html" title="twisted.internet.interfaces.IReactorUDP">twisted.internet.interfaces.IReactorUDP</a></code>
    reactor API.</p><h2>DatagramProtocol<a name="auto1"></a></h2><p>At the base, the place where you actually implement the protocol parsing
    and handling, is the DatagramProtocol class. This class will usually be decended
    from <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.DatagramProtocol.html" title="twisted.internet.protocol.DatagramProtocol">twisted.internet.protocol.DatagramProtocol</a></code>. Most
    protocol handlers inherit either from this class or from one of its
    convenience children. The DatagramProtocol class receives datagrams, and can
    send them out over the network. Received datagrams include the address they
    were sent from, and when sending datagrams the address to send to must
    be specified.</p><p>Here is a simple example:</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">DatagramProtocol</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</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-newline">
</span><span class="py-src-nl">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">Echo</span><span class="py-src-op">(</span><span class="py-src-parameter">DatagramProtocol</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span>    <span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">datagramReceived</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">data</span><span class="py-src-op">,</span> <span class="py-src-op">(</span><span class="py-src-parameter">host</span><span class="py-src-op">,</span> <span class="py-src-parameter">port</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">&quot;received %r from %s:%d&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">data</span><span class="py-src-op">,</span> <span class="py-src-variable">host</span><span class="py-src-op">,</span> <span class="py-src-variable">port</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">transport</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-variable">data</span><span class="py-src-op">,</span> <span class="py-src-op">(</span><span class="py-src-variable">host</span><span class="py-src-op">,</span> <span class="py-src-variable">port</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">listenUDP</span><span class="py-src-op">(</span><span class="py-src-number">9999</span><span class="py-src-op">,</span> <span class="py-src-variable">Echo</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">run</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-endmarker"></span></pre><p>As you can see, the protocol is registed with the reactor.
    This means it may be persisted if it's added to an application,
    and thus it has
    <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.DatagramProtocol.startProtocol.html" title="twisted.internet.protocol.DatagramProtocol.startProtocol">twisted.internet.protocol.DatagramProtocol.startProtocol</a></code> and 
    <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.protocol.DatagramProtocol.stopProtocol.html" title="twisted.internet.protocol.DatagramProtocol.stopProtocol">twisted.internet.protocol.DatagramProtocol.stopProtocol</a></code> methods that
    will get called when the protocol is connected and disconnected
    from a UDP socket.</p><p>The protocol's <code class="python">transport</code> attribute will implement the
    <code class="API"><a href="http://twistedmatrix.com/documents/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.interfaces.IUDPTransport.html" title="twisted.internet.interfaces.IUDPTransport">twisted.internet.interfaces.IUDPTransport</a></code>
    interface. Notice that the <code class="python">host</code> argument should be an IP,
    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/TwistedDocs/TwistedDocs-1.3.0/api/twisted.internet.interfaces.IReactorCore.resolve.html" title="twisted.internet.interfaces.IReactorCore.resolve">twisted.internet.interfaces.IReactorCore.resolve</a></code>).</p><h2>Connected UDP<a name="auto2"></a></h2><p>A connected UDP socket is slighly different from a standard one - it can
    only send and receive datagrams to/from a single address, but this does
    not in any way imply a connection. Datagrams may still arrive in any order,
    and the port on the other side may have no one listening. The benefit
    of the connected UDP socket is that it is faster.</p><p>Unlike a regular UDP protocol, we do not need to specify where to
    send datagrams to, and are not told where they came from since
    they can only come from address the socket is 'connected' to.</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</span><span class="py-src-variable">internet</span><span class="py-src-op">.</span><span class="py-src-variable">protocol</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">DatagramProtocol</span><span class="py-src-newline">
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</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-newline">
</span><span class="py-src-nl">
</span><span class="py-src-keyword">class</span> <span class="py-src-identifier">Helloer</span><span class="py-src-op">(</span><span class="py-src-parameter">DatagramProtocol</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-indent">    </span><span class="py-src-keyword">def</span> <span class="py-src-identifier">startProtocol</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-variable">d</span> <span class="py-src-op">=</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">transport</span><span class="py-src-op">.</span><span class="py-src-variable">connect</span><span class="py-src-op">(</span><span class="py-src-string">&quot;192.168.1.1&quot;</span><span class="py-src-op">,</span> <span class="py-src-number">1234</span><span class="py-src-op">)</span><span class="py-src-newline">
</span>        <span class="py-src-variable">d</span><span class="py-src-op">.</span><span class="py-src-variable">addCallback</span><span class="py-src-op">(</span><span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">_cbConnected</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">_cbConnected</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-op">(</span><span class="py-src-parameter">host</span><span class="py-src-op">,</span> <span class="py-src-parameter">port</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">&quot;we can only send to %s now&quot;</span> <span class="py-src-op">%</span> <span class="py-src-variable">str</span><span class="py-src-op">(</span><span class="py-src-op">(</span><span class="py-src-variable">host</span><span class="py-src-op">,</span> <span class="py-src-variable">port</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span> <span class="py-src-variable">self</span><span class="py-src-op">.</span><span class="py-src-variable">transport</span><span class="py-src-op">.</span><span class="py-src-variable">write</span><span class="py-src-op">(</span><span class="py-src-string">&quot;hello&quot;</span><span class="py-src-op">)</span> <span class="py-src-comment"># no need for address</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span>    <span class="py-src-dedent"></span><span class="py-src-keyword">def</span> <span class="py-src-identifier">datagramReceived</span><span class="py-src-op">(</span><span class="py-src-parameter">self</span><span class="py-src-op">,</span> <span class="py-src-parameter">data</span><span class="py-src-op">,</span> <span class="py-src-op">(</span><span class="py-src-parameter">host</span><span class="py-src-op">,</span> <span class="py-src-parameter">port</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">        </span><span class="py-src-keyword">print</span> <span class="py-src-string">&quot;received %r from %s:%d&quot;</span> <span class="py-src-op">%</span> <span class="py-src-op">(</span><span class="py-src-variable">data</span><span class="py-src-op">,</span> <span class="py-src-variable">host</span><span class="py-src-op">,</span> <span class="py-src-variable">port</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-comment"># 0 means any port, we don't care in this case
</span><span class="py-src-dedent"></span><span class="py-src-dedent"></span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">listenUDP</span><span class="py-src-op">(</span><span class="py-src-number">0</span><span class="py-src-op">,</span> <span class="py-src-variable">Helloer</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">run</span><span class="py-src-op">(</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-endmarker"></span></pre><p>Note that <code class="python">connect()</code>, like <code class="python">write()</code> will only accept IP addresses, not
  unresolved domain names. To obtain the IP of a domain name use <code class="python">reactor.resolve()</code>, e.g.:</p><pre class="python">
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span><span class="py-src-op">.</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-newline">
</span><span class="py-src-nl">
</span><span class="py-src-keyword">def</span> <span class="py-src-identifier">gotIP</span><span class="py-src-op">(</span><span class="py-src-parameter">ip</span><span class="py-src-op">)</span><span class="py-src-op">:</span><span class="py-src-newline">
</span><span class="py-src-indent">	</span><span class="py-src-keyword">print</span> <span class="py-src-string">&quot;IP of 'example.com' is&quot;</span><span class="py-src-op">,</span> <span class="py-src-variable">ip</span><span class="py-src-newline">
</span><span class="py-src-nl">
</span><span class="py-src-dedent"></span><span class="py-src-variable">reactor</span><span class="py-src-op">.</span><span class="py-src-variable">resolve</span><span class="py-src-op">(</span><span class="py-src-string">'example.com'</span><span class="py-src-op">)</span><span class="py-src-op">.</span><span class="py-src-variable">addCallback</span><span class="py-src-op">(</span><span class="py-src-variable">gotIP</span><span class="py-src-op">)</span><span class="py-src-newline">
</span><span class="py-src-endmarker"></span></pre><p>Connecting to a new address after a previous connection, or
	making a connected port unconnected are not currently supported,
	but will likely be supported in the future.</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 1.3.0</span></body></html>