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
精彩评论