2015-06-17 3 views
3

Я использую Twisted в программе python. Я отправляю данные каждую минуту и ​​получаю данные по сокету UDP, и мне нужно установить тайм-аут.Установить тайм-аут для UDP-сокета с Twisted (python)

Я нашел способ сделать это, но я хотел бы знать, если это хороший способ сделать это.

Это идея моего кода:

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

Спасибо за ваши советы

EDIT:

Это работает, но у меня есть проблема.

Если произошел тайм-аут, я правильно вхожу в функцию raise_timeout, но когда вызывается следующая «send_data()», функция self.transport.write («data») вызывает исключение: «NoneType 'объект не имеет атрибута' write '.

Я предполагаю, что сам.транспорт отключен.

Как это исправить?

+0

- это зависит от вашего конкретного случая использования? –

+0

Я просто хочу создать тайм-аут. Как и в библиотеке сокетов, когда мы использовали «socket.settimeout (5)» для повышения ошибки таймаута, когда мы это делаем »socket.recvfrom (1024)» – Damgot

+0

И какова цель тайм-аута? Если мы не получаем подтверждение в x раз, мы поднимаем тайм-аут и прерываем? Разве это не TCP? –

ответ

0

Я нашел решение.

Когда мы используем UDP, когда мы отправляем дейтаграмму, если ответ не получен менее чем за 1 секунду, для «self.transport» установлено значение None и вызывается метод «stopProtocol». Как только мы покинем метод stopProtocol, реактор перестанет прослушивать указанный UDP-порт.

Так что это мой код решение: «это хорошая идея»

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