[Twisted-Python] UDP asynchronous communication

Jp Calderone exarkun at divmod.com
Sun Apr 10 12:48:40 EDT 2005


On Sun, 10 Apr 2005 19:18:38 +0300, Adrian Libotean <adrian.libotean at asylum-studios.ro> wrote:
>Tommi Virtanen wrote:
>  > Adrian Libotean wrote:
>  >
>  >> Trust me I've read the document and after:
>  >>
>  >> reactor.listenUDP(...)
>  >> reactor.run()
>  >>
>  >> the *client* just waits for incoming traffic.
>  >
>  >
>  > Set up things to happen, then call reactor.run() at the end
>  > of your main function.
> 
> That's the problem: I just want to start the client and then, when the 
> user selects "Scan" from the interface, I must send the broadcast and 
> then act on replies from servers completely independent of the main 
> thread of the application.
> 
> So I have two choices: I run the reactor in a separate thread, or I find 
> a way to do a non-blocking communication using onReceive/onSend events.
> 

  The latter sounds like a great option to me.  Using a fictional widget library and a mega trivial protocol that just sends around "int:string" packets, here's how you do it:

    from twisted.internet import protocol, defer

    class ServiceDiscoveryDatagramProtocol(protocol.DatagramProtocol):
        def __init__(self):
            self.packets = {}
            self.counter = 0

        def _makeAPacket(self, hint):
            self.counter += 1
            d = self.packets[self.counter] = defer.Deferred()
            return d, '%d:%s' % (self.counter, hint)

        def _parseAPacket(self, bytes):
            counter, payload = bytes.split(':')
            return self.packets.pop(int(counter)), payload

        def discoverSomething(self, hint):
            d, pkt = self._makeAPacket(hint)
            self.transport.write(pkt)
            return d

        def datagramReceived(self, dgram, addr):
            d, stuff = self._parseAPacket(dgram)
            d.callback(stuff)

    from fiction import widgetlib

    class MainWidget(widgetlib.Frame):
        def __init__(self, proto):
            self.proto = proto
            self.discoverButton = widgetlib.Button(self, 
                                                   onClick=self._clicked)
            self.textArea = widgetlib.Text(self, 'Nothing to see')
            self.textArea.show()
            self.discoverButton.show()

        def _clicked(self):
            d = self.proto.discoverSomething('puppies')
            d.addCallback(self._discovered)

        def _discovered(self, what):
            self.textArea.setText(str(what))

    proto = ServiceDiscoveryDatagramProtocol()
    reactor.listenUDP(0, proto)
    main = MainWidget(proto)
    main.show()
    reactor.run()

  As you can see, all that is involved is hooking up sources of events to code which is interested in events.  Your widget library should generate events for user input.  Twisted will generate events for network traffic.  Each lets you define a function which is invoked when events occur.  All you need to do is define the functions in such a way as to make your program do what you want it to do :)

  Hope this helps,

  Jp




More information about the Twisted-Python mailing list