处理twisted中的ConnectionLost异常
我无法处理连接丢失的异常。首先,我设置了与jabber服务器的连接并进行ping测试。我使用的是wokkel库。然后,我在发送ping的函数中添加了错误回调(errback)。在这个错误回调中,我处理连接丢失的错误。之后,我关闭了互联网连接。但我看不到这个连接丢失的错误是否被处理。我在我的应用程序中关闭了连接,所有的异常处理程序都被调用了。
ping测试是成功的。
[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'>/>»
连接丢失的处理程序没有被调用。“在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,但它对连接丢失没有反应)。有没有人能给我一些在twisted中实现重新连接的例子?
脚本示例。运行这个脚本(确保ping测试正常)。然后关闭你的互联网连接。当发生几次ping后,你需要终止这个脚本。正如你所看到的,连接丢失的错误在关闭连接后被处理。
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
协议(Protocol)包含了以下内容:
clientConnectionFailed(self, connector, reason)
clientConnectionLost(self, connector, reason)
你可以重写这两个方法,并调用
PingClientProtocol.clientConnectionFailed和
PingClientProtocol.clientConnectionLost
假设 PingClientProtocol 是从 Protocol 继承来的某种形式。