2010-09-17 9 views
5

Sto provando a scrivere un semplice programma utilizzando il framework Twisted e sto lottando con la risoluzione (o anche con l'imaging come scriverlo) problema non sono riuscito a trovare alcuna documentazione pertinente per:Invio dei dati ricevuti in una fabbrica a torsione alla seconda fabbrica

Il reattore principale utilizza due stabilimenti, uno personalizzato, in attesa di connessioni TCP su una determinata porta (ad esempio, 8000) e un secondo, per accedere a un determinato server e canale IRC. Alla ricezione di dati (semplice, un testo di linea) sulla factory in ascolto su 8000, ho bisogno di passare quei dati al secondo factory, in modo che possa essere poi elaborato di conseguenza - o inviare un messaggio con quel testo a un canale, o un messaggio privato ad una persona, questo non è molto importante ora. Non riesco a trovare alcun modo per ottenere i dati dal primo stabilimento e inviarli a un altro, per l'elaborazione (forse come la solita connessione ricevuta per il secondo stabilimento IRC?).

Se questo potrebbe essere in qualche modo risolto, poi vorrei aggiungere una o anche più fabbriche (Jabber per esempio) per inviare i dati ricevuti sulla porta 8000 a tutti loro in una sola volta, di passare di conseguenza ai protocolli (IRC a un canale, Jabber a un contatto e così via).

C'è qualcuno che ha incontrato un problema simile ed è disposto a darmi qualche consiglio o addirittura condividere alcune righe di codice? Qualsiasi aiuto sarà molto apprezzato!

Grazie in anticipo.

risposta

6

Le fabbriche sono solo oggetti. Per passare i dati da uno all'altro, si definiscono e si chiamano i metodi e si passano i dati come parametro o si impostano gli attributi. Penso che questo faq question vi aiuterà a:

Come faccio a fare ingresso su una connessione risultato in uscita su un altro?

Questo sembra come se fosse un ritorto domanda, ma in realtà si tratta di una Python domanda. Ogni oggetto Protocol rappresenta una connessione; puoi chiamare transport.write per scrivere alcuni dati . Questi sono normali oggetti Python ; è possibile inserirli in elenchi, i dizionari o qualsiasi altra struttura di dati appropriata per l'applicazione .

Come semplice esempio, aggiungere un elenco per vostra fabbrica, e in di connectionMade e connectionLost vostro protocollo, aggiungere per e rimuoverlo da quella lista. Ecco il codice 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

Grazie per la risposta, ma ho visto che e questo non è esattamente quello che sto chiedendo - il vostro esempio invia i dati a molti clienti all'interno della stessa fabbrica, mentre il mio problema sembra un po 'più ampio - l'invio dei dati tra le fabbriche. Ho provato a usarli come oggetti, ma senza fortuna. Forse mi mancava la conoscenza di quali metodi chiamare quando si utilizza factory in modo insolito (mentre il modo usuale per una fabbrica è ricevere una connessione). – SpankMe

+0

@SpankMe: Beh, non riesco a immaginare cosa stai facendo, che non puoi risolvere creando normali metodi python sulle tue fabbriche e chiamandoli. Forse dovresti modificare la tua domanda e aggiungere un piccolo codice di esempio di ciò che vuoi fare. – nosklo

0

Credo che il tuo commento di cui sopra è nella giusta direzione - è necessario avere un riferimento o un 'manico' per l'oggetto che si desidera inviare i dati.

In altre parole, l'oggetto factory di invio deve avere un riferimento per l'oggetto factory di ricezione se si desidera utilizzare la comunicazione da oggetto a oggetto - cioè le chiamate di metodo. Un modo per ottenere ciò è che il nome della fabbrica ricevente venga passato alla fabbrica di invio all'inizializzazione.

Non è sempre ovvio dagli esempi, ma una fabbrica può avere i dati passati ad esso quando viene inizializzato.Ad esempio, nel caso di sopra della linea che crea la MultiEchoFactory potrebbe essere modificato per:

reactor.listenTCP(4321, MultiEchoFactory(someOtherObject)) 

e l'oggetto MultiEchoFactory sé modificato nella sua init metodo:

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

Ora avete un riferimento alla l'altro oggetto e chiama i metodi su di esso.

Un altro approccio potrebbe essere quello di avere un oggetto completamente separato a cui tutte le fabbriche hanno un riferimento all'inizializzazione e che funge da server di "ricerca" per i riferimenti a oggetti quando un oggetto vuole parlare a un altro. Questa funzionalità potrebbe essere fornita da una funzione se preferisci non utilizzare un oggetto.

0

Il modo in cui lo faccio è creare una classe contenitore.

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

Questo non può essere il metodo migliore ma funziona e permette una certa flessibilità

+0

In questo esempio, utilizzo solo uno stabilimento e ascolto su due porte. Nella tua domanda hai menzionato la connessione a un server irc. Questo dovrebbe essere semplice con questo metodo. Basta aggiungere le variabili rilevanti al factory irc client __init__ e aggiungere i metodi message_siblings, message_sibling etc. – tomfmason