2010-09-17 16 views
5

Je suis en train d'écrire un programme simple en utilisant Twisted cadre et je suis aux prises avec résoudre (ou même avec l'imagerie comment l'écrire) problème Je ne pouvais pas trouver toute documentation pertinente pour:Envoi de données reçues dans une usine Twisted à la deuxième usine

Le réacteur principal utilise deux usines, une personnalisée, à l'écoute des connexions TCP sur un port donné (disons 8000) et une seconde, pour se connecter au serveur et au canal IRC donnés. Lors de la réception de données (simple, un texte de ligne) en usine à 8000, je dois transmettre ces données à la seconde usine, afin qu'elles puissent être traitées en conséquence - soit envoyer un message avec ce texte à un canal, soit un message privé à quelqu'un, ce n'est pas vraiment important maintenant. Je ne peux pas trouver un moyen d'obtenir les données de la première usine et l'envoyer à un autre, pour le traitement (peut-être comme d'habitude la connexion reçue pour la deuxième usine IRC?). Si cela peut être résolu d'une façon ou d'une autre, alors je voudrais ajouter une ou plusieurs usines (Jabber par exemple) pour envoyer les données reçues sur le port 8000 à tous en même temps, pour le passer en conséquence aux protocoles (IRC à un canal, Jabber à un contact, et ainsi de suite).

Y at-il quelqu'un qui a rencontré un problème similaire et est prêt à me donner des conseils ou même partager des lignes de code? Toute aide sera grandement appréciée!

Merci d'avance.

Répondre

6

Les usines ne sont que des objets. Pour transmettre des données de l'un à l'autre, vous définissez et appelez des méthodes et transmettez les données en tant que paramètre ou définissez des attributs. Je pense que ce faq question vous aidera:

Comment puis-je faire des commentaires sur une connexion résultat dans la sortie sur un autre?

Cela semble que c'est un Twisted question, mais en réalité il est une question Python . Chaque objet Protocol représente une connexion; vous pouvez appeler son transport.write pour y écrire des données . Ce sont des objets normaux Python ; vous pouvez les mettre dans des listes, des dictionnaires , ou tout autre structure de données est approprié à votre application .

Comme un exemple simple, ajoutez une liste à votre usine, et dans votre protocole de connectionMade et connectionLost, ajoutez à et le retirer de cette liste. Voici le code Python:

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

Merci pour la réponse, mais j'ai vu que ce n'est pas exactement ce que je demande à propos - votre exemple envoie les données à beaucoup de clients dans la même usine, alors que mon problème semble un peu plus large - envoyer les données entre les usines. J'ai essayé de les utiliser comme des objets, mais sans chance. Peut-être manquais-je la connaissance des méthodes à utiliser lors de l'utilisation de l'usine de cette façon inhabituelle (alors que la manière habituelle pour une usine est de recevoir une connexion). – SpankMe

+0

@SpankMe: Eh bien, je ne peux pas imaginer ce que vous faites, que vous ne pouvez pas résoudre en créant des méthodes python normales sur vos usines et en les appelant. Peut-être que vous devriez éditer votre question et ajouter un petit exemple de code de ce que vous voulez faire. – nosklo

0

Je pense que votre commentaire ci-dessus est dans le bon sens - vous devez avoir une référence ou une « poignée » pour l'objet que vous souhaitez envoyer les données. En d'autres termes, l'objet expéditeur doit avoir une référence pour l'objet usine destinataire si vous souhaitez utiliser la communication objet-objet, c'est-à-dire les appels de méthode. Une façon d'y parvenir est que le nom de l'usine de réception soit transmis à l'usine émettrice lors de l'initialisation.

Ce n'est pas toujours évident à partir d'exemples mais une usine peut recevoir des données lors de son initialisation.Par exemple, dans le cas ci-dessus la ligne qui crée le MultiEchoFactory pourrait être modifié pour:

reactor.listenTCP(4321, MultiEchoFactory(someOtherObject)) 

et la méthode objet MultiEchoFactory lui-même modifié, il est init:

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

Maintenant, vous avez une référence à l'autre objet et appelle des méthodes sur elle. Une autre approche pourrait être d'avoir un objet complètement séparé auquel toutes vos usines sont référencées à l'initialisation, et qui agit comme une sorte de serveur de recherche de références d'objet quand un objet veut parler à un autre. Cette fonctionnalité pourrait être fournie par une fonction si vous préférez ne pas utiliser un objet.

0

La façon dont je le fais est en créant une classe de conteneur.

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() 

Cela peut ne pas être la meilleure méthode, mais il fonctionne et permet une certaine flexibilité

+0

Dans cet exemple, je n'utilise qu'une seule usine et j'écoute sur deux ports. Dans votre question, vous avez mentionné la connexion à un serveur irc. Cela devrait être simple avec cette méthode. Ajoutez simplement les variables pertinentes à la fabrique de clients irc __init__ et ajoutez les méthodes message_siblings, message_sibling etc. – tomfmason