Je me rends compte que je suis probablement stupide et qu'il manque quelque chose de grand et d'important, mais je n'arrive pas à comprendre comment spécifier un timeout en twisted en utilisant reactor.listenUDP. Mon but est de pouvoir spécifier un timeout, et après ce laps de temps, si DatagramProtocol.datagramReceived n'a pas été exécuté, faites-lui exécuter un callback ou quelque chose que je peux utiliser pour appeler reactor.stop(). Toute aide ou conseil est apprécié. MerciEst-il possible de définir un délai d'attente sur une socket dans Twisted?
Répondre
Depuis Twisted est piloté par les événements, vous n'avez pas besoin d'un délai d'attente en soi. Il vous suffit de définir une variable d'état (comme datagramRecieved) lorsque vous recevez un datagramme et enregistrer un looping call qui vérifie la variable d'état, arrête le réacteur si variable appropriée efface alors l'état:
from twisted.internet import task
from twisted.internet import reactor
datagramRecieved = False
timeout = 1.0 # One second
# UDP code here
def testTimeout():
global datagramRecieved
if not datagramRecieved:
reactor.stop()
datagramRecieved = False
l = task.LoopingCall(testTimeout)
l.start(timeout) # call every second
# l.stop() will stop the looping calls
reactor.run()
Je pense que reactor.callLater
fonctionnerait mieux que LoopingCall
. Quelque chose comme ceci:
class Protocol(DatagramProtocol):
def __init__(self, timeout):
self.timeout = timeout
def datagramReceived(self, datagram):
self.timeout.cancel()
# ...
timeout = reactor.callLater(5, timedOut)
reactor.listenUDP(Protocol(timeout))
avec le réacteur nous devons utiliser callLater. Démarrer le compte à rebours du délai d'attente lors de la connexionMade. Réinitialiser le compte à rebours du délai d'attente lorsque la ligne est reçue.
Voici le
# -*- coding: utf-8 -*-
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor, defer
_timeout = 27
class ServiceProtocol(LineReceiver):
def __init__(self, users):
self.users = users
def connectionLost(self, reason):
if self.users.has_key(self.name):
del self.users[self.name]
def timeOut(self):
if self.users.has_key(self.name):
del self.users[self.name]
self.sendLine("\nOUT: 9 - Disconnected, reason: %s" % 'Connection Timed out')
print "%s - Client disconnected: %s. Reason: %s" % (datetime.now(), self.client_ip, 'Connection Timed out')
self.transport.loseConnection()
def connectionMade(self):
self.timeout = reactor.callLater(_timeout, self.timeOut)
self.sendLine("\nOUT: 7 - Welcome to CAED")
def lineReceived(self, line):
# a simple timeout procrastination
self.timeout.reset(_timeout)
class ServFactory(Factory):
def __init__(self):
self.users = {} # maps user names to Chat instances
def buildProtocol(self, addr):
return ServiceProtocol(self.users)
port = 8123
reactor.listenTCP(port, ServFactory())
print "Started service at port %d\n" % port
reactor.run()
Une meilleure façon de le faire est avec twisted.protocols.policies.TimeoutMixin
. Il fait essentiellement un callLater
mais a abstraité dans un Mixin
.