Welcome, guest | Sign In | My Account | Store | Cart

A simple program using Twisted Perspective Broker and showing use of Twisted Deferreds and other callback mechanisms. Start the server without arguments and the client with the host name of the server.

Python, 62 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from twisted.spread import pb
from twisted.internet import reactor
        
import sys

PORT = 8992

DELAY         = 1
DOG_DELAY     = 2
RESTART_DELAY = 5

class Pinger:

    def __init__( self, host ):
        self.ping = None
        self.host = host
        self.ball = 0
        self._start()
        
    def _start( self ):
        print 'Waiting for Server...'
        dfr = pb.getObjectAt( self.host, PORT, 30 )
        dfr.addCallbacks( self._gotRemote, self._remoteFail )
    
    def _gotRemote( self, remote ):
        remote.notifyOnDisconnect( self._remoteFail )
        self.remote = remote
        self._ping()

    def _remoteFail( self, _ ):
        if self.ping:
            self.ping.cancel()
            self.ping = None
        self.restart = reactor.callLater( RESTART_DELAY, self._start )

    def _ping( self ):
        self.dog = reactor.callLater( DOG_DELAY, self._start )
        self.ball += 1
        print 'THROW', self.ball,
        dfr = self.remote.callRemote( 'Pong', self.ball )
        dfr.addCallbacks( self._pong, self._remoteFail )
            
    def _pong( self, ball ):
        self.dog.cancel()
        print 'CATCH',  ball
        self.ball = ball
        self.ping = reactor.callLater( DELAY, self._ping )

class Ponger( pb.Root ):

    def remote_Pong( self, ball ):
        print 'CATCH', ball,
        ball += 1
        print 'THROW', ball
        return ball 

if len( sys.argv ) > 1 :
    Pinger( sys.argv[1] )
else:
    reactor.listenTCP( PORT, pb.BrokerFactory( Ponger()))

reactor.run()

If the connection fails for any reason then the client should attempt to reconnect. If you kill the server then the client will wait for it to be restarted. Would be nice to have a graphical display that shows a ball being thrown from host to host.

2 comments

Mike Bott 13 years, 12 months ago  # | flag

I'm n00b to Twisted and trying to learn by reading everything I can get my eyes on. I felt that this recipe went a long way toward my "getting it" about pb, and I wish I had read this example a couple weeks ago.

I had to modify Pinger._start() as follows to get it to work on a recent Twisted since pb.getObjectAt() is no longer around:

def _start( self ):
    print 'Waiting for Server...'
    clientfactory = pb.PBClientFactory()
    reactor.connectTCP(self.host, PORT, clientfactory)        
    dfr = clientfactory.getRootObject()
    dfr.addCallbacks( self._gotRemote, self._remoteFail )
Arie Skliarouk 9 years, 4 months ago  # | flag

Twisted version 13.2.0 requires the listenTCP to be modified a bit: reactor.listenTCP( PORT, pb.PBServerFactory( Ponger()))