簡體   English   中英

互聯網離線時如何維護Channel API連接

[英]How to maintain Channel API connection when internet is offline

我正在使用Google AppEngine的Channel API。 由於用戶的網絡連接,我在重新啟動丟失的連接時遇到了一些問題。 當您斷開Internet連接時,通道將調用onError,但不會調用onClose。 就JavaScript對象而言,通道套接字是打開的。

您如何處理由於互聯網問題導致的連接丟失? 我在想1)通過觸發關閉通道並在與應用程序某處的通道無關的RPC首次成功執行時(這表明Internet再次存在)來關閉通道並重新打開它;或2)使用運行所有時間並ping服務器以獲取網絡狀態(這是引入長時間輪詢的目的,以避免以此方式消耗不需要的資源)。 任何其他想法都會很棒。

觀察:當互聯網連接中斷時,將以增量間隔(10秒,20秒,40秒)兩次調用onError。 互聯網連接恢復后,頻道不會恢復連接。 它停止工作,沒有任何跡象表明它已經死了。

謝謝。

當您看到JavaScript控制台時,大概會看到“ 400 Unknown SID Error”。 如果是這樣,這是我的解決方法。 這是AngularJS的服務模塊,但請查看onerror回調。 請嘗試這種解決方法,讓我知道它是否有效。

補充:我忽略了回答您的主要問題,但是在我看來,除非實際ping通“互聯網”,否則很難確定您是否已連接到Internet。 因此,您可能需要進行一些調整,以使用類似於以下代碼的重試邏輯。 在下面的示例中,我僅重試3次,但是您可以通過一些補償來做更多。 但是,我認為處理此問題的最佳方法是,當應用消耗重試最大計數時,您可以指示用戶該應用失去了連接,理想情況下,它會顯示一個按鈕或一個鏈接以重新連接到頻道服務。

而且,您還可以在服務器端跟蹤連接,請參閱: https : //developers.google.com/appengine/docs/java/channel/#Java_Tracking_client_connections_and_disconnections

app.factory('channelService', ['$http', '$rootScope', '$timeout',
  function($http, $rootScope, $timeout) {
    var service = {};
    var isConnectionAlive = false;
    var callbacks = new Array();
    var retryCount = 0;
    var MAX_RETRY_COUNT = 3;

    service.registerCallback = function(pattern, callback) {
      callbacks.push({pattern: pattern, func: callback});
    };

    service.messageCallback = function(message) {
      for (var i = 0; i < callbacks.length; i++) {
        var callback = callbacks[i];
        if (message.data.match(callback.pattern)) {
          $rootScope.$apply(function() {
            callback.func(message);
          });
        }
      }
    };

    service.channelTokenCallback = function(channelToken) {
      var channel = new goog.appengine.Channel(channelToken);
      service.socket = channel.open();
      isConnectionAlive = false;
      service.socket.onmessage = service.messageCallback;

      service.socket.onerror = function(error) {
        console.log('Detected an error on the channel.');
        console.log('Channel Error: ' + error.description + '.');
        console.log('Http Error Code: ' + error.code);
        isConnectionAlive = false;
        if (error.description == 'Invalid+token.' || error.description == 'Token+timed+out.') {
          console.log('It should be recovered with onclose handler.');
        } else {
          // In this case, we need to manually close the socket.
          // See also: https://code.google.com/p/googleappengine/issues/detail?id=4940
          console.log('Presumably it is "Unknown SID Error". Try closing the socket manually.');
          service.socket.close();
        }
      };

      service.socket.onclose = function() {
        isConnectionAlive = false;
        console.log('Reconnecting to a new channel');
        openNewChannel();
      };

      console.log('A channel was opened successfully. Will check the ping in 20 secs.');
      $timeout(checkConnection, 20000, false);
    };

    function openNewChannel(isRetry) {
      console.log('Retrieving a clientId.');
      if (isRetry) {
        retryCount++;
      } else {
        retryCount = 0;
      }
      $http.get('/rest/channel')
          .success(service.channelTokenCallback)
          .error(function(data, status) {
            console.log('Can not retrieve a clientId');
            if (status != 403 && retryCount <= MAX_RETRY_COUNT) {
              console.log('Retrying to obtain a client id')
              openNewChannel(true);
            }
          })
    }

    function pingCallback() {
      console.log('Got a ping from the server.');
      isConnectionAlive = true;
    }

    function checkConnection() {
      if (isConnectionAlive) {
        console.log('Connection is alive.');
        return;
      }
      if (service.socket == undefined) {
        console.log('will open a new connection in 1 sec');
        $timeout(openNewChannel, 1000, false);
        return;
      }
      // Ping didn't arrive
      // Assuming onclose handler automatically open a new channel.
      console.log('Not receiving a ping, closing the connection');
      service.socket.close();
    }

    service.registerCallback(/P/, pingCallback);
    openNewChannel();

    return service;
  }]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM