2013-08-15 3 views
1

Я пытаюсь цепи deferreds в клиенте AMP, как следующее:Chaining отложила обратные вызовы

Клиент:

from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol 
from twisted.protocols.amp import AMP 

import commands 

def connect_protocol(host, port): 
    destination = TCP4ClientEndpoint(reactor, host, port) 
    d = connectProtocol(destination, AMP()) 

    def connect(protocol): 
     print 'Connecting to server as Mr Spaceman...' 
     return protocol.callRemote(commands.Connect, 
            username='Mr Foo') 

    def say(protocol): 
     print 'Saying "Hello world" to the server...' 
     return protocol.callRemote(commands.Say, 
            phrase='Hello world') 

    d.addCallback(connect) 
    d.addCallback(say) 


def main(host, port): 
    connect_protocol(host, port) 
    print 'Connected to %s:%d...' % (host, port) 
    reactor.run() 

main('127.0.0.1', 12345) 

Сервер:

from twisted.internet.protocol import Factory 
from twisted.protocols.amp import AMP 

import commands 

class CommandProtocol(AMP): 

    def connect(self, username): 
     print "Received connect command: %s." % (username) 
     return {} 
    commands.Connect.responder(connect) 

    def say(self, phrase): 
     print "Received phrase \"%s\"." % phrase 
     return {} 
    commands.Say.responder(say) 

def main(port): 
    factory = Factory() 
    factory.protocol = CommandProtocol 
    reactor.listenTCP(port, factory) 
    print 'Started AMP server on port %d...' % port 
    reactor.run() 

main(12345) 

Только connect() стреляют на стороне сервера

ответ

1

Во-первых, включить ведение журнала:

from sys import stdout 
from twisted.python.log import startLogging 
startLogging(stdout) 

Теперь вы увидите, что происходит в программе.

Во-вторых, по крайней мере, иметь окончательный errback, который регистрирует необработанное отказы на Deferred поэтому они будут отображаться детерминировано, а не в зависимости от сборщика мусора:

from twisted.python.log import err 

... 

    d.addCallback(connect) 
    d.addCallback(say) 
    d.addErrback(err, "connect_protocol encountered some problem") 

Наконец, результат отложенное изменяется на обратные вызовы и исправления, прикрепленные к нему. В этом случае аргумент, переданный say, является результатом Deferred, возвращенным connect. Это не будет то же самое, что аргумент connect, так что вряд ли вы можете использовать callRemote.

Вы можете исправить это разными способами. Один из способов, который включает в себя минимальные изменения кода (но не обязательно самое лучшее решение) является передать протокол в качестве дополнительного значения в результате connectDeferred:

def connect(protocol): 
    print 'Connecting to server as Mr Spaceman...' 
    d = protocol.callRemote(commands.Connect, username='Mr Foo') 
    d.addCallback(lambda result: (protocol, result)) 
    return d 

def say((protocol, result)): 
    print 'Saying "Hello world" to the server...' 
    return protocol.callRemote(commands.Say, 
           phrase='Hello world') 
+1

'd.addCallback (скажем)' 'преформ callRemote' на dict, но как мне сделать 2 несвязанных вызова от одного и того же клиента к одному и тому же серверу ('connect' и' say')? –

Смежные вопросы