2008-11-24 9 views
23

Estoy buscando una manera de enviar periódicamente algunos datos sobre todos los clientes conectados a un puerto TCP. Estoy mirando una pitón retorcida y estoy al tanto de reactor.callLater. ¿Pero cómo lo uso para enviar datos a todos los clientes conectados periódicamente? La lógica de envío de datos está en la clase de protocolo y el reactor lo instancia según sea necesario. No sé cómo vincularlo desde el reactor a todas las instancias de protocolo ...Ejecutando una función periódicamente en el protocolo twisted

Respuesta

37

Es probable que desee hacer esto en la fábrica para las conexiones. La Fábrica no se notifica automáticamente cada vez que se realiza y pierde una conexión, por lo que puede notificarlo desde el Protocolo.

Este es un ejemplo completo de cómo usar twisted.internet.task.LoopingCall junto con una fábrica y protocolo básicos personalizados para anunciar que '10 segundos han pasado' a cada conexión cada 10 segundos.

from twisted.internet import reactor, protocol, task 

class MyProtocol(protocol.Protocol): 
    def connectionMade(self): 
     self.factory.clientConnectionMade(self) 
    def connectionLost(self, reason): 
     self.factory.clientConnectionLost(self) 

class MyFactory(protocol.Factory): 
    protocol = MyProtocol 
    def __init__(self): 
     self.clients = [] 
     self.lc = task.LoopingCall(self.announce) 
     self.lc.start(10) 

    def announce(self): 
     for client in self.clients: 
      client.transport.write("10 seconds has passed\n") 

    def clientConnectionMade(self, client): 
     self.clients.append(client) 

    def clientConnectionLost(self, client): 
     self.clients.remove(client) 

myfactory = MyFactory() 
reactor.listenTCP(9000, myfactory) 
reactor.run() 
+0

¡Gracias! Esto ayudó mucho. Estaba tratando de manejar el envío de datos en la clase de protocolo y tenía problemas para no tener acceso a todos los clientes (¡tenía una clase singleton para contenerlos a todos!). Hacer esto en la subclase de fábrica tiene mucho más sentido. Reescribiré mi código ... ¡Gracias! – Amit

+0

¿Cómo escribirías una prueba para verificar que un cliente obtiene "* 10 segundos ha pasado \ n *" seis veces en un minuto? – Sardathrion

3

Me imagino que la manera más fácil de hacerlo es administrar una lista de clientes en el protocolo con connectionMade y connectionLost en el cliente y luego use un LoopingCall para pedirle a cada cliente que envíe datos.

Eso se siente un poco invasivo, pero no creo que quieras hacerlo sin que el protocolo tenga cierto control sobre la transmisión/recepción. Por supuesto, tendría que ver tu código para saber realmente cómo encajaría bien. ¿Tienes un enlace de Github? :)

+0

Tengo la versión inicial en funcionamiento. El reactor.callLater se puede llamar a cualquier parte, así que terminé llamándolo desde connectionMade(). Sin embargo, ahora el problema es que cada conexión obtiene su propio temporizador y datos. Realmente me gustaría tener un solo temporizador y datos. (como una transmisión) ... – Amit

Cuestiones relacionadas