2016-10-07 4 views
4

아우토반을 사용하여 websocket에 연결하고 있습니다.autobahn websocket timeout 후 다시 연결하는 방법?

class MyComponent(ApplicationSession): 

    @inlineCallbacks 
    def onJoin(self, details): 
    print("session ready") 

    def oncounter(*args, **args2): 
     print("event received: args: {} args2: {}".format(args, args2)) 

    try: 
     yield self.subscribe(oncounter, u'topic') 
     print("subscribed to topic") 
    except Exception as e: 
     print("could not subscribe to topic: {0}".format(e)) 

if __name__ == '__main__': 
    addr = u"wss://mywebsocketaddress.com" 
    runner = ApplicationRunner(url=addr, realm=u"realm1", debug=False, debug_app=False) 
    runner.run(MyComponent) 

위대한 작품이며, 메시지를받을 수 있습니다. 그러나 약 3-4 시간 후, 때로는 훨씬 더 일찍 메시지가 갑자기 오지 않습니다. websocket 시간 초과 (그 일이?), 아마도 연결 문제로 인해 나타납니다.

자동 밴은 어떻게 자동 응답 할 수 있습니까?


내 시도이지만 재접속 코드는 호출되지 않습니다.

class MyClientFactory(ReconnectingClientFactory, WampWebSocketClientFactory): 

    maxDelay = 10 
    maxRetries = 5 

    def startedConnecting(self, connector): 
     print('Started to connect.') 

    def clientConnectionLost(self, connector, reason): 
     print('Lost connection. Reason: {}'.format(reason)) 
     ReconnectingClientFactory.clientConnectionLost(self, connector, reason) 

    def clientConnectionFailed(self, connector, reason): 
     print('Connection failed. Reason: {}'.format(reason)) 
     ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) 

class MyApplicationRunner(object): 

    log = txaio.make_logger() 

    def __init__(self, url, realm, extra=None, serializers=None, 
       debug=False, debug_app=False, 
       ssl=None, proxy=None): 

     assert(type(url) == six.text_type) 
     assert(realm is None or type(realm) == six.text_type) 
     assert(extra is None or type(extra) == dict) 
     assert(proxy is None or type(proxy) == dict) 
     self.url = url 
     self.realm = realm 
     self.extra = extra or dict() 
     self.serializers = serializers 
     self.debug = debug 
     self.debug_app = debug_app 
     self.ssl = ssl 
     self.proxy = proxy 

    def run(self, make, start_reactor=True): 
     if start_reactor: 
      # only select framework, set loop and start logging when we are asked 
      # start the reactor - otherwise we are running in a program that likely 
      # already tool care of all this. 
      from twisted.internet import reactor 
      txaio.use_twisted() 
      txaio.config.loop = reactor 

      if self.debug or self.debug_app: 
       txaio.start_logging(level='debug') 
      else: 
       txaio.start_logging(level='info') 

     isSecure, host, port, resource, path, params = parseWsUrl(self.url) 

     # factory for use ApplicationSession 
     def create(): 
      cfg = ComponentConfig(self.realm, self.extra) 
      try: 
       session = make(cfg) 
      except Exception as e: 
       if start_reactor: 
        # the app component could not be created .. fatal 
        self.log.error(str(e)) 
        reactor.stop() 
       else: 
        # if we didn't start the reactor, it's up to the 
        # caller to deal with errors 
        raise 
      else: 
       session.debug_app = self.debug_app 
       return session 

     # create a WAMP-over-WebSocket transport client factory 
     transport_factory = MyClientFactory(create, url=self.url, serializers=self.serializers, 
                 proxy=self.proxy, debug=self.debug) 

     # supress pointless log noise like 
     # "Starting factory <autobahn.twisted.websocket.WampWebSocketClientFactory object at 0x2b737b480e10>"" 
     transport_factory.noisy = False 

     # if user passed ssl= but isn't using isSecure, we'll never 
     # use the ssl argument which makes no sense. 
     context_factory = None 
     if self.ssl is not None: 
      if not isSecure: 
       raise RuntimeError(
        'ssl= argument value passed to %s conflicts with the "ws:" ' 
        'prefix of the url argument. Did you mean to use "wss:"?' % 
        self.__class__.__name__) 
      context_factory = self.ssl 
     elif isSecure: 
      from twisted.internet.ssl import optionsForClientTLS 
      context_factory = optionsForClientTLS(host) 

     from twisted.internet import reactor 
     if self.proxy is not None: 
      from twisted.internet.endpoints import TCP4ClientEndpoint 
      client = TCP4ClientEndpoint(reactor, self.proxy['host'], self.proxy['port']) 
      transport_factory.contextFactory = context_factory 
     elif isSecure: 
      from twisted.internet.endpoints import SSL4ClientEndpoint 
      assert context_factory is not None 
      client = SSL4ClientEndpoint(reactor, host, port, context_factory) 
     else: 
      from twisted.internet.endpoints import TCP4ClientEndpoint 
      client = TCP4ClientEndpoint(reactor, host, port) 

     d = client.connect(transport_factory) 

     # as the reactor shuts down, we wish to wait until we've sent 
     # out our "Goodbye" message; leave() returns a Deferred that 
     # fires when the transport gets to STATE_CLOSED 
     def cleanup(proto): 
      if hasattr(proto, '_session') and proto._session is not None: 
       if proto._session.is_attached(): 
        return proto._session.leave() 
       elif proto._session.is_connected(): 
        return proto._session.disconnect() 

     # when our proto was created and connected, make sure it's cleaned 
     # up properly later on when the reactor shuts down for whatever reason 
     def init_proto(proto): 
      reactor.addSystemEventTrigger('before', 'shutdown', cleanup, proto) 
      return proto 

     # if we connect successfully, the arg is a WampWebSocketClientProtocol 
     d.addCallback(init_proto) 

     # if the user didn't ask us to start the reactor, then they 
     # get to deal with any connect errors themselves. 
     if start_reactor: 
      # if an error happens in the connect(), we save the underlying 
      # exception so that after the event-loop exits we can re-raise 
      # it to the caller. 

      class ErrorCollector(object): 
       exception = None 

       def __call__(self, failure): 
        self.exception = failure.value 
        reactor.stop() 
      connect_error = ErrorCollector() 
      d.addErrback(connect_error) 

      # now enter the Twisted reactor loop 
      reactor.run() 

      # if we exited due to a connection error, raise that to the 
      # caller 
      if connect_error.exception: 
       raise connect_error.exception 

     else: 
      # let the caller handle any errors 
      return d 

오류 내가 갖는 : 당신이 트위스트를 사용하는 경우

 
2016-10-09T21:00:40+0100 Connection to/from tcp4:xxx.xx.xx.xx:xxx was lost in a non-clean fashion: Connection lost 
2016-10-09T21:00:40+0100 _connectionLost: [Failure instance: Traceback (failure with no frames): : Connection to the other side was lost in a non-clean fashion: Connection l 
ost. 
] 
2016-10-09T21:00:40+0100 WAMP-over-WebSocket transport lost: wasClean=False, code=1006, reason="connection was closed uncleanly (peer dropped the TCP connection without previous WebSocket closing handshake)" 
2016-10-09T21:10:39+0100 EXCEPTION: no messages received 
2016-10-09T21:10:39+0100 Traceback (most recent call last): 

답변

0

당신은 ReconnectingClientFactory를 사용할 수 있습니다. There's a simple example by the autobahn developer on github. 불행히도이 기능이 사전 빌드 된 ApplicationRunner 구현이없는 것 같지만 직접 구현하기는 어렵지 않습니다. Here's an asyncio variant 트위스트로 직선이어야합니다. 당신은 클라이언트가 재접속하는 것을 통합하기 위해 dev 팀이 원하는 것처럼 보이기 때문에 this issue을 따를 수 있습니다.

+0

나는 꼬인 상태로 SSL 검증을 비활성화하는 방법을 알아 냈으므로 그 문제에 봉착했습니다. (당신은 내 (bizso09) [여기 Github 코멘트] (https://github.com/twisted/treq/issues/65#issuecomment-250070129) 링크. 내가 ReconnectingClientFactory 구현하려고하는 질문을 편집했지만 코드를 다시 연결 감사합니다. – siamii

+0

주목해야 할 점 중 하나는 공장 클래스에서 재접속 지연을 재설정 할 호출이 없다는 것입니다 (예 : [''self.resetDelay()']). (https://twistedmatrix.com/documents/current/api/twisted.internet.protocol.ReconnectingClientFactory.html#resetDelay)) Twisted를 사용하여 간격을두고 기다리는 대신 빨리 다시 연결하려고하면이 작업을 수행해야 할 수도 있습니다. 이것이 재 연결이 일어나지 않는 이유인지 확실하지 않습니다. –

+0

다른 문제는 'clientConnectionLost' 메서드가 호출되지 않는다는 것입니다. 오류 출력 로그에서 볼 수 있듯이 print 문은 없습니다. . 원본에서 인쇄 된 오류를 추적하고'WampWebSocketC 세션의'onClose' 메소드를 호출하는 lientProtocol 클래스. 이것은 ReconnectingFactory를 완전히 우회하는 것 같습니다. 또한, 제 경우에는 강제로 연결을 끊는 서버가 나타납니다. 그러나 중요하지 않아야합니까? – siamii

0

여기에 자동으로 다시 연결되는 ApplicationRunner의 example이 있습니다. 자동 재 연결을 가능하게하는 중요한 라인은 다음과 같습니다

runner.run(session, auto_reconnect=True) 

당신은 또한 B)까지)에, (예를 들어 Crossbar.io에서) 자동 웹 소켓 핑/탁구를 활성화 연결이 때문에 시간 제한을 삭제합니다 최소화하려면, 것 손실 된 연결을 빠르게 검색 할 수 있습니다.

1

pip3 install autobahn-autoreconnect을 사용해 보셨습니까?

# from autobahn.asyncio.wamp import ApplicationRunner 
from autobahn_autoreconnect import ApplicationRunner 
관련 문제