Set timeout for UDP socket with Twisted (python)
I am using Twisted in a python program. I am sending data every minute and receiving data in UDP juice and I need to set a timeout.
I found a way to do this, but I would like to know if this is a good way to do it.
This is the idea behind my code:
class UDPSocket(DatagramProtocol):
def startProtocol(self):
self.transport.connect(self.HOST, self.PORT)
reactor.callLater(1, self.send_data)
def send_data(self):
reactor.callLater(60, self.send_data)
self.transport.write("Some data")
self.timeoutCallId = reactor.callLater(5, raise_timeout)
def datagramReceived(self, data, (host, port)):
if self.timeoutCallId.active():
self.timeoutCallId.cancel()
#Do something with data
def raise_timeout(self):
#Do something to manage timeout
reactor.listenUDP(port, UDPSocket())
reactor.run()
Thanks for your advice
EDIT:
This works, but I have a problem.
If a timeout occurs, I correctly enter the raise_timeout function, but when the next "send_data ()" is called, the self.transport.write ("data") function raises an exception: The "NoneType" object has no "write" attribute.
I think self.transport is disabled.
How can I fix this?
source to share
I found a solution.
When we use UDP, when we send a datagram, if no response is received in less than 1 second, "self.transport" is set to None and the "stopProtocol" method is called. As soon as we leave the stopProtocol method, the reactor will stop listening on the specified UDP port.
So this is my solution code:
class UDPSocket(DatagramProtocol):
def __init__(self, mainreactor):
self._reactor = mainreactor
def startListenUDP(self):
try :
self._reactor.listenUDP(KeepAlive.PORT, self)
except Exception, e :
pass
def startProtocol(self) :
self.transport.connect(self.host, self.port)
def stopProtocol(self):
print "Transport disconnected !"
self._reactor.callLater(0.1, self.startListenUDP)
def raise_timeout(self) :
print "Timeout !"
def datagramReceived(self, datagram, host):
try :
if self.timeout_id.active():
self.timeout_id.cancel()
except Exception, e :
pass
print datagram
def sendDatagram(self):
datagram = "Some Data"
try :
self.transport.write(datagram)
self.timeout_id = self._reactor.callLater(TIMEOUT,
self.raise_timeout)
except Exception, e :
self._reactor.callLater(0.1, self.startListenUDP)
def main():
protocol = UDPSocket(reactor)
t = reactor.listenUDP(PORT, protocol)
l = task.LoopingCall(protocol.sendDatagram)
l.start(60)
reactor.run()
#MAIN
if __name__ == '__main__':
main()
source to share