Twisted のソケットにタイムアウトを設定することはできますか?
-
03-07-2019 - |
質問
おそらく私が愚かで、大きくて重要なことを見逃しているだけであることは理解していますが、reactor.listenUDP を使用してツイストでタイムアウトを指定する方法がわかりません。私の目標は、タイムアウトを指定できるようにすることです。指定した時間が経過した後、DatagramProtocol.datagramReceived が実行されていない場合は、コールバックまたは、reactor.stop() を呼び出すために使用できるものを実行させるようにすることです。助けやアドバイスをいただければ幸いです。ありがとう
解決
Twisted はイベント駆動型であるため、タイムアウト自体は必要ありません。データグラムを受信し、データグラムを登録するときに状態変数 (datagramRecieved など) を設定するだけです。 ループ呼び出し 状態変数をチェックし、必要に応じてリアクターを停止し、状態変数をクリアします。
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()
他のヒント
reactor.callLater
は、 LoopingCall
よりも優れていると思います。このようなもの:
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))
リアクターでは、callLaterを使用する必要があります。 connectionMadeのときにタイムアウトのカウントダウンを開始します。 lineReceived時にタイムアウトのカウントダウンをリセットします。
これが
# -*- 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()
これを行うより良い方法は、 twisted.protocols.policies.TimeoutMixin
を使用することです。基本的には callLater
を実行しますが、 Mixin
に抽象化されます。
所属していません StackOverflow