处理twisted中的ConnectionLost异常

发布于 2024-10-15 10:41:30 字数 4058 浏览 3 评论 0原文

我无法处理 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尬尬 2024-10-22 10:41:30

协议具有:

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

您可以覆盖两者并调用
PingClientProtocol.clientConnectionFailed
和 PingClientProtocol.clientConnectionLost

假设 PingClientProtocol 以某种方式从 Protocol 继承

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文