Je cherche un moyen d'envoyer périodiquement des données sur tous les clients connectés à un port TCP. Je regarde python tordu et je suis au courant de reactor.callLater. Mais comment l'utiliser pour envoyer périodiquement des données à tous les clients connectés? La logique d'envoi de données est dans la classe Protocol et est instanciée par le réacteur si nécessaire. Je ne sais pas comment lier de réacteur à toutes les instances de protocole ...Exécution périodique d'une fonction en protocole tordu
Répondre
Vous voudrez probablement faire cela à l'usine pour les connexions. L'usine n'est pas automatiquement avertie chaque fois qu'une connexion est établie et perdue, vous pouvez donc la notifier à partir du protocole.
Voici un exemple complet d'utilisation de twisted.internet.task.LoopingCall en conjonction avec une Usine de base et un Protocole personnalisés pour annoncer que '10 secondes s'est écoulées' à chaque connexion toutes les 10 secondes.
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()
Je pense que la façon la plus simple de le faire est de gérer une liste de clients dans le protocole avec connectionMade et connectionLost dans le client et utilisez ensuite LoopingCall pour demander à chaque client d'envoyer des données.
Cela semble un peu envahissant, mais je ne pense pas que vous voudriez le faire sans le protocole ayant un certain contrôle sur la transmission/réception. Bien sûr, je devrais voir votre code pour vraiment savoir comment il s'intégrerait bien. Vous avez un lien github? :)
J'ai obtenu la version initiale de travail. Le reactor.callLater peut être appelé n'importe où, donc j'ai fini par l'appeler depuis connectionMade(). Cependant, maintenant le problème est que chaque connexion reçoit son propre timer et ses propres données. Je voudrais vraiment une seule minuterie et des données. (comme une diffusion) ... – Amit
Merci! Cela a beaucoup aidé. J'essayais de gérer l'envoi des données dans la classe de protocole et j'avais des problèmes pour ne pas avoir accès à tous les clients (j'avais une classe singleton pour les contenir tous!)! Faire cela dans la sous-classe d'usine est beaucoup plus logique. Je vais réécrire mon code ... Merci! – Amit
Comment écririez-vous un test pour vérifier qu'un client obtient «* 10 secondes a passé \ n *» six fois dans une minute? – Sardathrion