Ejecutar una función periódicamente en protocolo retorcido
Pregunta
Estoy buscando una forma de enviar periódicamente algunos datos a través de todos los clientes conectados a un puerto TCP. Estoy mirando Python retorcido y soy consciente de reactor.callLater. Pero, ¿cómo lo uso para enviar algunos 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 la instancia según sea necesario. No sé cómo vincularlo desde el reactor a todas las instancias de protocolo ...
Solución
Probablemente quiera hacer esto en la Fábrica para las conexiones. La Fábrica no recibe una notificación automática de cada vez que se realiza y se pierde una conexión, por lo que puede notificarlo desde el Protocolo.
Aquí hay un ejemplo completo de cómo usar twisted.internet.task.LoopingCall junto con una Fábrica y un 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()
Otros consejos
Me imagino que la forma más fácil de hacerlo es administrar una lista de clientes en el protocolo con connectionMade y connectionLost en el cliente y luego usar una LoopingCall para pedirle a cada cliente que envíe datos.
Eso se siente un poco invasivo, pero no creo que quiera hacerlo sin que el protocolo tenga algún control sobre la transmisión / recepción. Por supuesto, tendría que ver su código para saber realmente cómo encajaría bien. ¿Tienes un enlace github? :)