2010-09-17 14 views
5

Ich versuche, ein einfaches Programm mit Twisted-Framework zu schreiben und ich habe Probleme mit Auflösung (oder sogar mit Imaging, wie es geschrieben) Problem Ich konnte keine relevante Dokumentation finden für:Senden von Daten in einem Twisted Factory zu zweiten Fabrik

Der Hauptreaktor verwendet zwei Fabriken, eine benutzerdefinierte, die auf TCP-Verbindungen auf einem gegebenen Port (zB 8000) hört, und zweiten, um sich bei einem gegebenen IRC-Server und Kanal anzumelden. Beim Empfang von Daten (einfacher, einzeiliger Text) in der Fabrik, die bei 8000 abhört, muss ich diese Daten an die zweite Fabrik weitergeben, damit sie dann entsprechend verarbeitet werden kann - entweder eine Nachricht mit diesem Text an einen Kanal oder eine Priv-Nachricht senden zu einer Person, das ist jetzt nicht wirklich wichtig. Ich kann keinen Weg finden, um die Daten von der ersten Fabrik zu erhalten und sie zu einem anderen zu senden, für die Verarbeitung (vielleicht wie üblich erhaltener Anschluss für die zweite IRC-Fabrik?).

Wenn dies irgendwie gelöst werden könnte, würde ich gerne eine oder sogar mehrere Fabriken (Jabber zum Beispiel) hinzufügen, um die empfangenen Daten über Port 8000 an alle gleichzeitig zu senden, um sie entsprechend an Protokolle (IRC zu einem Kanal, Jabber zu einem Kontakt und so weiter).

Gibt es jemanden, der ein ähnliches Problem hatte und bereit ist, mir einen Rat zu geben oder sogar einige Zeilen Code zu teilen? Jede Hilfe wird sehr geschätzt!

Vielen Dank im Voraus.

Antwort

6

Fabriken sind nur Objekte. Um Daten von einem zum anderen zu übertragen, definieren und rufen Sie Methoden auf und übergeben die Daten als Parameter oder setzen Attribute. Ich denke, das faq question wird Ihnen helfen:

Wie kann ich Eingang auf einer Verbindung Ergebnis in Ausgabe auf ein anderes zu machen?

Dies scheint, wie es eine verdrehte Frage, aber es ist eigentlich eine Frage Python. Jedes Protocol Objekt stellt eine Verbindung dar; Sie können anrufen seine transport.write schreiben Sie einige Daten zu ihm. Dies sind normale Python Objekte; Sie können sie in Listen einfügen, Wörterbücher, oder was auch immer andere Daten Struktur ist passend zu Ihrer Anwendung.

Als einfaches Beispiel, um eine Liste zu Ihrer Fabrik hinzufügen und in Ihrem Protokoll der connectionMade und connectionLost, fügt es zu und entfernen sie aus dieser Liste. Hier ist der Python-Code:

from twisted.internet.protocol import Protocol, Factory 
from twisted.internet import reactor 

class MultiEcho(Protocol): 
    def connectionMade(self): 
     self.factory.echoers.append(self) 
    def dataReceived(self, data): 
     for echoer in self.factory.echoers: 
      echoer.transport.write(data) 
    def connectionLost(self, reason): 
     self.factory.echoers.remove(self) 

class MultiEchoFactory(Factory): 
    protocol = MultiEcho 
    def __init__(self): 
     self.echoers = [] 

reactor.listenTCP(4321, MultiEchoFactory()) 
reactor.run() 
+0

Danke für die Antwort, aber ich sah, dass und das ist nicht genau das, was ich bin zu fragen - Ihr Beispiel der Daten sendet für viele Kunden innerhalb der gleichen Fabrik, während mein Problem scheint ein bisschen breiter - Senden der Daten zwischen den Fabriken. Ich habe versucht, sie als Objekte zu verwenden, aber ohne Glück. Vielleicht fehlte mir das Wissen, welche Methoden man bei der Verwendung von Factory auf diese ungewöhnliche Art und Weise anruft (während der übliche Weg für eine Fabrik eine Verbindung erhält). – SpankMe

+0

@SpankMe: Nun, ich kann mir nicht vorstellen, was Sie tun, das Sie nicht lösen können, indem Sie normale Python-Methoden in Ihren Fabriken erstellen und aufrufen. Vielleicht sollten Sie Ihre Frage bearbeiten und einen kleinen Beispielcode hinzufügen, was Sie tun möchten. – nosklo

0

Ich denke, Ihr Kommentar oben in die richtige Richtung ist - für das Objekt einen Verweis oder einen ‚Griff‘ haben, müssen Sie, um die Daten zu senden.

Mit anderen Worten muss das sendende Factory-Objekt eine Referenz für das empfangende Factory-Objekt haben, wenn Sie Objekt-zu-Objekt-Kommunikation verwenden möchten - also Methodenaufrufe. Eine Möglichkeit, dies zu erreichen, besteht darin, dass der Name der empfangenden Fabrik bei der Initialisierung an die sendende Fabrik weitergeleitet wird.

Es ist nicht immer aus Beispielen ersichtlich, aber eine Fabrik kann Daten haben, wenn sie initialisiert werden.Zum Beispiel im Fall oberhalb der Linie, die die MultiEchoFactory schafft modifiziert werden könnte:

reactor.listenTCP(4321, MultiEchoFactory(someOtherObject)) 

und das MultiEchoFactory Objekt selbst in seinem init Methode geändert:

class MultiEchoFactory(Factory): 
    protocol = MultiEcho 
    def __init__(self, otherObjectReference): 
     self.echoers = [] 
     self.otherObject = otherObjectReference 

Jetzt haben Sie einen Verweis auf das andere Objekt und Aufrufmethoden darauf. Ein anderer Ansatz könnte darin bestehen, ein vollständig separates Objekt zu haben, auf das alle Ihre Fabriken bei der Initialisierung verweisen, und das als eine Art Nachschlage-Server für Objektreferenzen fungiert, wenn ein Objekt mit einem anderen sprechen möchte. Diese Funktionalität könnte von einer Funktion bereitgestellt werden, wenn Sie kein Objekt verwenden möchten.

0

Die Art, wie ich es mache, ist durch Erstellen einer Container-Klasse.

from twisted.internet.protocol import Protocol, Factory 
from twisted.internet import reactor 

class QOTD(Protocol): 

    def connectionMade(self): 
     self.factory.message_siblings("Got a client") 
     self.transport.loseConnection() 

class MyFactory(Factory): 
    protocol = QOTD 
    def __init__(self,root,name): 
     self.clients = [] 
     self.root = root 
     self.name = name 
     #self.root.add_child(name,self) 
    def message_siblings(self,message): 
     self.root.message_children(self.name,message) 
    def message_sibling(self,message): 
     self.root.message_child(self.name,message) 
    def get_message(self,name,message): 
     #do something here 
     print name,message 



class Container(object): 
    def __init__(self): 
     self.servers = {} 
    def add_child(self,obj,name): 
     self.servers[name] = obj(self,name) 
    def message_children(self,name,message): 
     for server in self.servers: 
      if server != name: 
       self.servers[server].get_message(name,message) 
    def message_child(self,name,message): 
     if name in self.servers.keys(): 
      self.servers[server].get_message(name,message) 

container = Container() 
container.add_child(MyFactory,'test') 
container.add_child(MyFactory,'test2') 
reactor.listenTCP(8007, container.servers['test']) 
reactor.listenTCP(8008, container.servers['test2']) 
reactor.run() 

Dies kann nicht die beste Methode sein, aber es funktioniert und ermöglicht eine gewisse Flexibilität

+0

In diesem Beispiel verwende ich nur die eine Fabrik und höre auf zwei Ports. In Ihrer Frage haben Sie erwähnt, dass Sie sich mit einem IRC-Server verbinden. Das sollte mit dieser Methode einfach sein. Fügen Sie einfach die relevanten Variablen zur irc-Client-Factory __init__ hinzu und fügen Sie die Methoden message_siblings, message_sibling usw. hinzu. – tomfmason