Обработка исключения ConnectionLost в витой - PullRequest
4 голосов
/ 31 января 2011

Я не могу обработать исключение ConnectionLost.Краткий пример того, что у меня есть.Прежде всего, я установил соединение с jabber-сервером и пропинговал его.Для этого я использую библиотеку wokkel.Затем я добавляю errback к методу, отправляющему ping.В errback я обрабатываю ошибку ConnectionLost.После этого я закрываю интернет-соединение.Но я не могу видеть, обработан ли тот ConnectionLost.Я закрываю соединение в моем приложении, и все обработчики исключений вызываются.

Пинг проходит хорошо.

[XmlStream,client] Ping to JID(u'jabber.ru') started at HivemindPingClientProtocol 
[-] SEND: «iq to='jabber.ru' type='get' id='H_3'>/>»
[XmlStream,client] RECV: "/><feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"

Интернет-соединение закрыто

[-] SEND: «iq to='jabber.ru' type='get' id='H_6'>/>»
[-] SEND: «iq to='jabber.ru' type='get' id='H_7'>/>»

Обработчики ConnectionLost не работаютвызывается.«Поток закрыт в HivemindXMPPClient» печатается в StreamManager методом _disconnected

[-] Protocol stopped
[-] Protocol closed
[-] Transport stopped
[XmlStream,client] Stream closed at HivemindXMPPClient

Все исключения обрабатываются после закрытия потока.

[XmlStream,client] Failure [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.
[XmlStream,client] Failure [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.] 
[XmlStream,client] Connection lost with [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.] 
[XmlStream,client] Stopping factory <hivemind.network.network_core.HivemindXmlStreamFactory object at 0xa2e904c>> 

Может кто-нибудь объяснить, почему после закрытия потока вызываются ошибки?На самом деле я хочу реализовать функцию переподключения (я уже использую ReconnectingFactory, но он не реагирует на ConnectionLost).Может кто-нибудь дать мне пример реализации переподключения в витой?

Пример скрипта. Запустите этот скрипт (убедитесь, что ping работает нормально).Затем закройте интернет-соединение.Когда произошло несколько пингов, вам необходимо прекратить выполнение сценария.Как видите, ошибки ConnectionLost обрабатываются после закрытия соединения.

import sys
from twisted.python import log
from twisted.words.protocols import jabber
from twisted.internet.error import ConnectionLost
from wokkel.client import XMPPClient
from wokkel.ping import PingClientProtocol
from twisted.internet.task import LoopingCall

JID = unicode('YOUR@JABBER.ID')
PASSWORD = 'PASSWORD'
INTERVAL = 3

class SpecialPingClientProtocol(PingClientProtocol):

    def __init__(self, entity, interval):
        self.__entity = jabber.jid.internJID(entity)
        self.__interval = interval
        self.__pingLoop = None

    def _onError(self, failure):
        log.msg('Failure %s at %s' % (failure, self.__class__.__name__))
        error = failure.trap(jabber.error.StanzaError, ConnectionLost)
        if error == jabber.error.StanzaError:
            if failure.value.condition == 'feature-not-implemented':
                return None
        elif error == ConnectionLost:
            # Do some beautiful things
            log.msg('Connection is lost. I want to reconnect NOW')
        return failure

    def _sendPing(self):
        defer = self.ping(self.__entity)
        defer.addErrback(self._onError)

    def stopPing(self):
        log.msg('Ping to %s stopped at %s' % (self.__entity, self.__class__.__name__))
        if self.__pingLoop is not None and self.__pingLoop.running:
            self.__pingLoop.stop()
            self.__pingLoop = None

    def startPing(self):
        log.msg('Ping to %s started at %s ' % (self.__entity, self.__class__.__name__))
        self.__pingLoop = LoopingCall(self._sendPing)
        self.__pingLoop.start(self.__interval, now = False)

def main():
    log.startLogging(sys.stdout)
    transport = XMPPClient(jabber.jid.internJID(JID), PASSWORD)
    transport.logTraffic = True
    pinger = SpecialPingClientProtocol(JID, INTERVAL)
    pinger.setHandlerParent(transport)
    transport.startService()
    pinger.startPing()
    reactor.run()

if __name__ == '__main__':
    from twisted.internet import reactor
    main()

1 Ответ

2 голосов
/ 22 мая 2011

Протокол имеет:

clientConnectionFailed(self, connector, reason)
clientConnectionLost(self, connector, reason)

, вы можете переопределить оба и вызвать PingClientProtocol.clientConnectionFailed и PingClientProtocol.clientConnectionLost

, предполагая, что PingClientProtocol каким-то образом наследуется от Protocol

...