2017-09-15 2 views
0

Je suis assez nouveau à Twisted, donc je suis sûr que c'est une erreur de débutant. J'ai construit un serveur simple qui reçoit un message du client et à la réception du message le serveur déclenche un rappel qui imprime le message à la console.Instance d'usine ne créant pas un nouveau différé

En première instance, le serveur fonctionne comme prévu. Malheureusement, lorsque je démarre un deuxième client, je reçois l'erreur suivante: "twisted.internet.defer.AlreadyCalledError". Je croyais que l'usine ferait une nouvelle instance de la différée, c'est-à-dire que la nouvelle différée n'aurait pas été appelée auparavant?

S'il vous plaît voir le code ci-dessous. Toute aide serait très appréciée.

import sys 
from twisted.internet.protocol import ServerFactory, Protocol 
from twisted.internet import defer 

class LockProtocol(Protocol): 

    lockData = '' 

    def dataReceived(self, data): 
    self.lockData += data 

    if self.lockData.endswith('??'): 
     self.lockDataReceived(self.lockData) 

    def lockDataReceived(self, lockData): 
    self.factory.lockDataFinished(lockData) 

class LockServerFactory(ServerFactory): 

    protocol = LockProtocol 

    def __init__(self): 
    self.deferred = defer.Deferred() # Initialise deferred 

    def lockDataFinished(self, lockData): 
     self.deferred.callback(lockData) 

    def clientConnectionFailed(self, connector, reason): 
     self.deferred.errback(reason) 


def main(): 

    HOST = '127.0.0.1' # localhost 
    PORT = 10001 

    def got_lockData(lockData): 
    print "We have received lockData. It is as follows:", lockData 

    def lockData_failed(err): 
    print >> sys.stderr, 'The lockData download failed.' 
    errors.append(err) 


    factory = LockServerFactory() 

    from twisted.internet import reactor 

    # Listen for TCP connections on a port, and use our factory to make a protocol instance for each new connection 

    port = reactor.listenTCP(PORT,factory) 

    print 'Serving on %s' % port.getHost() 

    # Set up callbacks 

    factory.deferred.addCallbacks(got_lockData,lockData_failed) 

    reactor.run() # Start the reactor 

if __name__ == '__main__': 
    main() 

Répondre

0

avis qu'il n'y a qu'un seul LockServerFactory jamais créé dans votre programme:

factory = LockServerFactory() 

Cependant, autant LockProtocol instances sont créées comme les connexions sont acceptées. Si vous avez l'état par connexion, l'emplacement est LockProtocol.

Il semble que votre événement «verrouillage des données terminé» ne soit pas un événement unique, donc un Deferred n'est probablement pas la bonne abstraction pour ce travail.

Au lieu d'un LockServerFactory avec un Deferred qui se déclenche lorsque cet événement se produit, peut-être vous voulez un gestionnaire d'événements multi-usage, peut-être construit sur mesure:

class LockServerFactory(ServerFactory): 

    protocol = LockProtocol 

    def __init__(self, lockDataFinished): 
    self.lockDataFinished = lockDataFinished 

factory = LockServerFactory(got_lockData) 

(Soit dit en passant, notez que je l'ai laissé tomber clientConnectionFailed de cette implémentation: c'est une méthode de ClientFactory Elle ne sera jamais appelée dans une usine de serveurs.)