I'm using Twisted in a python program. I send data every minute and receive data on a UDP socket and I need to set a timeout.
I found a way to do this, but I would like to know if it's a good way to do that.
This is the idea of 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 advices
EDIT :
It works but I have a problem.
If a timeout occured, I'm going into the raise_timeout function correctly, but when the next "send_data()" is called, the self.transport.write("data") function raise an exception : 'NoneType' object has no attribute 'write'.
I guess self.transport is disconnected.
How can I fix that ?
I found a solution.
When we use UDP, when we send a datagram, if no answer is received after less than 1 second, "self.transport" is set to None and "stopProtocol" method is called. Once we leave "stopProtocol" method, reactor stops to listen 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()