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?

+3


source to share


1 answer


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()

      

0


source







All Articles