开发者

Handling of ConnectionLost exception in twisted

I can not handle a ConnectionLost exception. Brief example of what I have. First of all iIset up connection to jabber server and ping it. I use wokkel library for that. Then I add errback to the method that is sending ping. In the errback I handle the ConnectionLost error. After that, I close the internet connection. But I can not see if that ConnectionLost is handled. I close connection in my application and all exception handlers are invoked.

Ping goes well.

[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'/>"

Internet connection is closed

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

Handlers of ConnectionLost are not invoked. "Stream closed at HivemindXMPPClient" is printed in StreamManager in _disconnected method

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

All exception are handled after closing stream.

[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'&开发者_如何学Pythongt;: Connection was closed cleanly.] 
[XmlStream,client] Stopping factory <hivemind.network.network_core.HivemindXmlStreamFactory object at 0xa2e904c>> 

Can anybody explain why errbacks are invoked after closing the stream? Actually I want to implement a reconnect feature(I already use ReconnectingFactory, but it does not react on ConnectionLost). Can someone give me some example of reconnect implementation in twisted?

Script example. Run this script (make sure that ping work fine). Then close your internet connection. When several ping has occured, you need to terminate the script. As you can see, ConnectionLost errors are handled after closing the connection.

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


Protocol has:

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

you can override both and call PingClientProtocol.clientConnectionFailed and PingClientProtocol.clientConnectionLost

assuming that PingClientProtocol inherit somehow from Protocol

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜