处理twisted中的ConnectionLost异常
我无法处理 ConnectionLost 异常。 我所拥有的简短示例。首先,我建立与 jabber 服务器的连接并对其执行 ping 操作。我为此使用 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'/>"
Internet 连接已关闭
[-] SEND: «iq to='jabber.ru' type='get' id='H_6'>/>»
[-] SEND: «iq to='jabber.ru' type='get' id='H_7'>/>»
ConnectionLost 的处理程序不会被调用。在 _disconnected 方法中的 StreamManager 中打印“在 HivemindXMPPClient 处关闭流”
[-] 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 工作正常)。然后关闭您的互联网连接。当出现多次 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('[email protected]')
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()
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'>: 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('[email protected]')
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()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
协议具有:
您可以覆盖两者并调用
PingClientProtocol.clientConnectionFailed
和 PingClientProtocol.clientConnectionLost
假设 PingClientProtocol 以某种方式从 Protocol 继承
Protocol has:
you can override both and call
PingClientProtocol.clientConnectionFailed
and PingClientProtocol.clientConnectionLost
assuming that PingClientProtocol inherit somehow from Protocol