国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter:WebSocket封裝-實(shí)現(xiàn)心跳、重連機(jī)制

這篇具有很好參考價(jià)值的文章主要介紹了Flutter:WebSocket封裝-實(shí)現(xiàn)心跳、重連機(jī)制。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前言Permalink
Flutter簡介

Flutter 是 Google推出并開源的移動(dòng)應(yīng)用開發(fā)框架,主打跨平臺、高保真、高性能。開發(fā)者可以通過 Dart語言開發(fā) App,一套代碼同時(shí)運(yùn)行在 iOS 和 Android平臺。 Flutter提供了豐富的組件、接口,開發(fā)者可以很快地為 Flutter添加 native擴(kuò)展。同時(shí) Flutter還使用 Native引擎渲染視圖,這無疑能為用戶提供良好的體驗(yàn)。

WebSocket簡介

Http協(xié)議是無狀態(tài)的,只能由客戶端主動(dòng)發(fā)起,服務(wù)端再被動(dòng)響應(yīng),服務(wù)端無法向客戶端主動(dòng)推送內(nèi)容,并且一旦服務(wù)器響應(yīng)結(jié)束,鏈接就會(huì)斷開(見注解部分),所以無法進(jìn)行實(shí)時(shí)通信。WebSocket協(xié)議正是為解決客戶端與服務(wù)端實(shí)時(shí)通信而產(chǎn)生的技術(shù),現(xiàn)在已經(jīng)被主流瀏覽器支持,所以對于Web開發(fā)者來說應(yīng)該比較熟悉了,F(xiàn)lutter也提供了專門的包來支持WebSocket協(xié)議。

注意:Http協(xié)議中雖然可以通過keep-alive機(jī)制使服務(wù)器在響應(yīng)結(jié)束后鏈接會(huì)保持一段時(shí)間,但最終還是會(huì)斷開,keep-alive機(jī)制主要是用于避免在同一臺服務(wù)器請求多個(gè)資源時(shí)頻繁創(chuàng)建鏈接,它本質(zhì)上是支持鏈接復(fù)用的技術(shù),而并非用于實(shí)時(shí)通信,讀者需要知道這兩者的區(qū)別。

WebSocket協(xié)議本質(zhì)上是一個(gè)基于tcp的協(xié)議,它是先通過HTTP協(xié)議發(fā)起一條特殊的http請求進(jìn)行握手后,如果服務(wù)端支持WebSocket協(xié)議,則會(huì)進(jìn)行協(xié)議升級。WebSocket會(huì)使用http協(xié)議握手后創(chuàng)建的tcp鏈接,和http協(xié)議不同的是,WebSocket的tcp鏈接是個(gè)長鏈接(不會(huì)斷開),所以服務(wù)端與客戶端就可以通過此TCP連接進(jìn)行實(shí)時(shí)通信。有關(guān)WebSocket協(xié)議細(xì)節(jié),讀者可以看RFC文檔,下面我們重點(diǎn)看看Flutter中如何使用WebSocket。

話不多說,直接擼代碼Permalink
添加依賴:

web_socket_channel: ^1.1.0 # WebSocket
新建web_socket_utility.dart工具類:

import 'dart:async';

import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

/// WebSocket地址
const String _SOCKET_URL = 'ws://121.40.165.18:8800';

/// WebSocket狀態(tài)
enum SocketStatus {
  SocketStatusConnected, // 已連接
  SocketStatusFailed, // 失敗
  SocketStatusClosed, // 連接關(guān)閉
}

class WebSocketUtility {
  /// 單例對象
  static WebSocketUtility _socket;

  /// 內(nèi)部構(gòu)造方法,可避免外部暴露構(gòu)造函數(shù),進(jìn)行實(shí)例化
  WebSocketUtility._();

  /// 獲取單例內(nèi)部方法
  factory WebSocketUtility() {
    // 只能有一個(gè)實(shí)例
    if (_socket == null) {
      _socket = new WebSocketUtility._();
    }
    return _socket;
  }

  IOWebSocketChannel _webSocket; // WebSocket
  SocketStatus _socketStatus; // socket狀態(tài)
  Timer _heartBeat; // 心跳定時(shí)器
  num _heartTimes = 3000; // 心跳間隔(毫秒)
  num _reconnectCount = 60; // 重連次數(shù),默認(rèn)60次
  num _reconnectTimes = 0; // 重連計(jì)數(shù)器
  Timer _reconnectTimer; // 重連定時(shí)器
  Function onError; // 連接錯(cuò)誤回調(diào)
  Function onOpen; // 連接開啟回調(diào)
  Function onMessage; // 接收消息回調(diào)

  /// 初始化WebSocket
  void initWebSocket({Function onOpen, Function onMessage, Function onError}) {
    this.onOpen = onOpen;
    this.onMessage = onMessage;
    this.onError = onError;
    openSocket();
  }

  /// 開啟WebSocket連接
  void openSocket() {
    closeSocket();
    _webSocket = IOWebSocketChannel.connect(_SOCKET_URL);
    print('WebSocket連接成功: $_SOCKET_URL');
    // 連接成功,返回WebSocket實(shí)例
    _socketStatus = SocketStatus.SocketStatusConnected;
    // 連接成功,重置重連計(jì)數(shù)器
    _reconnectTimes = 0;
    if (_reconnectTimer != null) {
      _reconnectTimer.cancel();
      _reconnectTimer = null;
    }
    onOpen();
    // 接收消息
    _webSocket.stream.listen((data) => webSocketOnMessage(data),
        onError: webSocketOnError, onDone: webSocketOnDone);
  }

  /// WebSocket接收消息回調(diào)
  webSocketOnMessage(data) {
    onMessage(data);
  }

  /// WebSocket關(guān)閉連接回調(diào)
  webSocketOnDone() {
    print('closed');
    reconnect();
  }

  /// WebSocket連接錯(cuò)誤回調(diào)
  webSocketOnError(e) {
    WebSocketChannelException ex = e;
    _socketStatus = SocketStatus.SocketStatusFailed;
    onError(ex.message);
    closeSocket();
  }

  /// 初始化心跳
  void initHeartBeat() {
    destroyHeartBeat();
    _heartBeat =
        new Timer.periodic(Duration(milliseconds: _heartTimes), (timer) {
      sentHeart();
    });
  }

  /// 心跳
  void sentHeart() {
    sendMessage('{"module": "HEART_CHECK", "message": "請求心跳"}');
  }

  /// 銷毀心跳
  void destroyHeartBeat() {
    if (_heartBeat != null) {
      _heartBeat.cancel();
      _heartBeat = null;
    }
  }

  /// 關(guān)閉WebSocket
  void closeSocket() {
    if (_webSocket != null) {
      print('WebSocket連接關(guān)閉');
      _webSocket.sink.close();
      destroyHeartBeat();
      _socketStatus = SocketStatus.SocketStatusClosed;
    }
  }

  /// 發(fā)送WebSocket消息
  void sendMessage(message) {
    if (_webSocket != null) {
      switch (_socketStatus) {
        case SocketStatus.SocketStatusConnected:
          print('發(fā)送中:' + message);
          _webSocket.sink.add(message);
          break;
        case SocketStatus.SocketStatusClosed:
          print('連接已關(guān)閉');
          break;
        case SocketStatus.SocketStatusFailed:
          print('發(fā)送失敗');
          break;
        default:
          break;
      }
    }
  }

  /// 重連機(jī)制
  void reconnect() {
    if (_reconnectTimes < _reconnectCount) {
      _reconnectTimes++;
      _reconnectTimer =
          new Timer.periodic(Duration(milliseconds: _heartTimes), (timer) {
        openSocket();
      });
    } else {
      if (_reconnectTimer != null) {
        print('重連次數(shù)超過最大次數(shù)');
        _reconnectTimer.cancel();
        _reconnectTimer = null;
      }
      return;
    }
  }
}

使用方法Permalink
import 'package:my_app/utils/web_socket_utility.dart';

WebSocketUtility().initWebSocket(onOpen: () {
  WebSocketUtility().initHeartBeat();
}, onMessage: (data) {
  print(data);
}, onError: (e) {
  print(e);
});

轉(zhuǎn)自:https://ricardolsw.github.io/blog/Flutter-WebSocket%E5%B0%81%E8%A3%85-%E5%AE%9E%E7%8E%B0%E5%BF%83%E8%B7%B3-%E9%87%8D%E8%BF%9E%E6%9C%BA%E5%88%B6/

更新dart版本后的代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-682664.html

import 'dart:async';

import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:kkview_kuaichuan/config.dart';
/// WebSocket狀態(tài)
enum SocketStatus {
  socketStatusConnected, // 已連接
  socketStatusFailed, // 失敗
  socketStatusClosed, // 連接關(guān)閉
}

class WebSocketUtility {
  /// 單例對象
  static final WebSocketUtility _socket = WebSocketUtility._internal();

  /// 內(nèi)部構(gòu)造方法,可避免外部暴露構(gòu)造函數(shù),進(jìn)行實(shí)例化
  WebSocketUtility._internal();

  /// 獲取單例內(nèi)部方法
  factory WebSocketUtility() {
    return _socket;
  }

  late WebSocketChannel _webSocket; // WebSocket
  SocketStatus? _socketStatus; // socket狀態(tài)
  Timer? _heartBeat; // 心跳定時(shí)器
  final int _heartTimes = 30000; // 心跳間隔(毫秒)
  final int _reconnectCount = 2; // 重連次數(shù),默認(rèn)60次
  int _reconnectTimes = 0; // 重連計(jì)數(shù)器
  Timer? _reconnectTimer; // 重連定時(shí)器
  late Function onError; // 連接錯(cuò)誤回調(diào)
  late Function onOpen; // 連接開啟回調(diào)
  late Function onMessage; // 接收消息回調(diào)



  /// 初始化WebSocket
  void initWebSocket({required Function onOpen, required Function onMessage, required Function onError}) {
    this.onOpen = onOpen;
    this.onMessage = onMessage;
    this.onError = onError;
    openSocket();
  }

  /// 開啟WebSocket連接
  void openSocket() {
    // closeSocket();
    _webSocket = WebSocketChannel.connect(Uri.parse(SIGNALSERVERURL));
    print('WebSocket連接成功: $SIGNALSERVERURL');
    // 連接成功,返回WebSocket實(shí)例
    _socketStatus = SocketStatus.socketStatusConnected;
    // 連接成功,重置重連計(jì)數(shù)器
    _reconnectTimes = 0;
    if (_reconnectTimer != null) {
      _reconnectTimer?.cancel();
      _reconnectTimer = null;
    }
    onOpen();
    // 接收消息
    _webSocket.stream.listen((data) => webSocketOnMessage(data),
        onError: webSocketOnError, onDone: webSocketOnDone);
  }

  /// WebSocket接收消息回調(diào)
  webSocketOnMessage(data) {
    onMessage(data);
  }

  /// WebSocket關(guān)閉連接回調(diào)
  webSocketOnDone() {
    print('webSocketOnDone closed');
    _socketStatus = SocketStatus.socketStatusClosed;
    reconnect();
  }

  /// WebSocket連接錯(cuò)誤回調(diào)
  webSocketOnError(e) {
    WebSocketChannelException ex = e;
    _socketStatus = SocketStatus.socketStatusFailed;
    onError(ex.message);
    closeSocket();
  }

  /// 初始化心跳
  void initHeartBeat() {
    destroyHeartBeat();
    _heartBeat =
    Timer.periodic(Duration(milliseconds: _heartTimes), (timer) {
      sentHeart();
    });
  }

  /// 心跳
  void sentHeart() {
    sendMessage('{"module": "HEART_CHECK", "message": "請求心跳"}');
  }

  /// 銷毀心跳
  void destroyHeartBeat() {
    if (_heartBeat != null) {
      _heartBeat?.cancel();
      _heartBeat = null;
    }
  }

  /// 關(guān)閉WebSocket
  void closeSocket() {
    print('WebSocket連接關(guān)閉');
    _webSocket.sink.close();
    destroyHeartBeat();
    _socketStatus = SocketStatus.socketStatusClosed;
  }

  /// 發(fā)送WebSocket消息
  void sendMessage(message) {
    switch (_socketStatus) {
      case SocketStatus.socketStatusConnected:
        print('發(fā)送中:$message');
        _webSocket.sink.add(message);
        break;
      case SocketStatus.socketStatusClosed:
        print('連接已關(guān)閉');
        break;
      case SocketStatus.socketStatusFailed:
        print('發(fā)送失敗');
        break;
      default:
        break;
    }
  }

  /// 重連機(jī)制
  void reconnect() {
    if (_reconnectTimes < _reconnectCount) {
      _reconnectTimes++;
      _reconnectTimer =
      Timer.periodic(Duration(milliseconds: _heartTimes), (timer) {
        openSocket();
      });
    } else {
      if (_reconnectTimer != null) {
        print('重連次數(shù)超過最大次數(shù)');
        _reconnectTimer?.cancel();
        _reconnectTimer = null;
      }
      return;
    }
  }

  get socketStatus => _socketStatus;
  get webSocketCloseCode => _webSocket.closeCode;


}

到了這里,關(guān)于Flutter:WebSocket封裝-實(shí)現(xiàn)心跳、重連機(jī)制的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • websocket的基礎(chǔ)使用,心跳機(jī)制,斷線重連

    websocket的基礎(chǔ)使用,心跳機(jī)制,斷線重連

    websoket出現(xiàn)的原因: 傳統(tǒng)的http請求只能是由前端向后臺發(fā)送一個(gè)請求,然后后臺把結(jié)果返回給前端,前端再進(jìn)行展示。這里就暴露了一個(gè)問題,就是通信只能由前端發(fā)起,而后臺無法主動(dòng)與前端通信。而websoket的出現(xiàn)就是為了解決這個(gè)問題,讓前端可以主動(dòng)聯(lián)系后臺,后臺也

    2024年02月06日
    瀏覽(26)
  • WebSocket實(shí)戰(zhàn)之六心跳重連機(jī)制

    WebSocket實(shí)戰(zhàn)之六心跳重連機(jī)制

    WebSocket應(yīng)用部署到生產(chǎn)環(huán)境,我們除了會(huì)碰到因?yàn)榻?jīng)過代理服務(wù)器無法連接的問題(注:該問題可以通過搭建WSS來解決,具體配置請看?WebSocket實(shí)戰(zhàn)之四WSS配置?),另外一個(gè)問題就是外網(wǎng)環(huán)境不穩(wěn)定經(jīng)常會(huì)斷開或者服務(wù)器重啟或者網(wǎng)絡(luò)中間服務(wù)器當(dāng)發(fā)現(xiàn)一個(gè)長連接長時(shí)間沒有

    2024年02月07日
    瀏覽(28)
  • uniapp使用WebSocket斷線,心跳重連機(jī)制

    提示:我們在使用WebSocket,經(jīng)常會(huì)遇到有的時(shí)候給別人發(fā)消息,別人會(huì)接收不到,這個(gè)時(shí)候就有可能是WebSocket斷線了,所以這個(gè)時(shí)候心跳包就出現(xiàn)了 提示:可直接使用,記得把對應(yīng)地址替換一下

    2024年04月12日
    瀏覽(31)
  • websocket實(shí)時(shí)通訊和socket.io實(shí)時(shí)通信庫的使用;心跳機(jī)制與斷線重連

    https://zh.javascript.info/websocket WebSocket 是一種網(wǎng)絡(luò)通信協(xié)議,就類似于 HTTP 也是一種通信協(xié)議。 為什么需要 WebSocket? 因?yàn)?HTTP 協(xié)議有一個(gè)缺陷:通信只能由客戶端發(fā)起。 代碼解析: 創(chuàng)建WebSocket實(shí)例:通過 new WebSocket() 創(chuàng)建一個(gè)WebSocket實(shí)例。在括號中傳入服務(wù)器的URL,該URL指定了

    2024年02月16日
    瀏覽(39)
  • vue3使用websocket簡易封裝,包含錯(cuò)誤重連機(jī)制

    vue3使用websocket簡易封裝,包含錯(cuò)誤重連機(jī)制

    websocket實(shí)現(xiàn)的全雙工通信,真真太香了,以下是筆者在使用時(shí),自己封裝的一個(gè)簡易js工具。若需要源碼,請移步這里 筆者這里會(huì)重連3次,重連的過程給與用戶提示,3次之后會(huì)提示用戶手動(dòng)刷新 這里與后端約定的數(shù)據(jù)返回,加上type作為接口判斷依據(jù),因此這里不一定通用。

    2024年02月11日
    瀏覽(29)
  • uni-app 封裝 websocket 并且監(jiān)聽心跳機(jī)制

    新建 socket.js , 將以下代碼復(fù)制進(jìn)去 ,向外暴露。 在入口文件中 將 socketIO 掛載在 Vue 原型上 , 也可以按需引入置頂頁面 。 在需要用到webSocket的頁面中使用如下方法(可根據(jù)自身業(yè)務(wù)需求進(jìn)行整改) 離開頁面,記得斷開連接。

    2024年02月11日
    瀏覽(18)
  • Vue 2 中 WebSocket 模塊實(shí)現(xiàn)與應(yīng)用(包含心跳檢測、自動(dòng)重連)

    Vue 2 中 WebSocket 模塊實(shí)現(xiàn)與應(yīng)用(包含心跳檢測、自動(dòng)重連)

    WebSocket 技術(shù)是一種在 Web 開發(fā)中常用的實(shí)時(shí)通信方式,它允許客戶端和服務(wù)器之間建立持久性的雙向連接,以便實(shí)時(shí)地傳輸數(shù)據(jù)。在 Vue.js 項(xiàng)目中,使用 WebSocket 可以輕松實(shí)現(xiàn)實(shí)時(shí)消息推送、即時(shí)通訊等功能。在這篇博客中,我們將介紹一個(gè)基于 Vue.js 的 WebSocket 模塊的實(shí)現(xiàn),

    2024年02月03日
    瀏覽(54)
  • WebSocket心跳重連在微信小程序中的實(shí)現(xiàn)與服務(wù)器端

    WebSocket技術(shù)是一種在瀏覽器和服務(wù)器之間建立持久化連接的通信協(xié)議。在微信小程序中,通過WebSocket可以實(shí)現(xiàn)實(shí)時(shí)的雙向通信。然而,由于網(wǎng)絡(luò)等各種因素的不穩(wěn)定性,WebSocket連接可能會(huì)出現(xiàn)斷開的情況。為了保證連接的可靠性,我們可以通過心跳機(jī)制和重連機(jī)制來處理Web

    2024年03月18日
    瀏覽(29)
  • C++ Qt TCP的心跳檢測機(jī)制,斷線重連技術(shù),應(yīng)用層代碼重新實(shí)現(xiàn)

    C++ Qt TCP的心跳檢測機(jī)制,斷線重連技術(shù),應(yīng)用層代碼重新實(shí)現(xiàn)

    目錄 前言: 一、Qt直接啟動(dòng)本身的KeepAlive 二、在應(yīng)用層自己實(shí)現(xiàn)一個(gè)心跳檢測 ?三、自定義心跳代碼實(shí)現(xiàn): 完整客戶端服務(wù)端工程下載: 共用的結(jié)構(gòu)體相關(guān)頭文件: ? ? ? ? 客戶端部分核心代碼: ? ? ? ? 服務(wù)端部分核心代碼: 運(yùn)行結(jié)果展示: 前兩篇關(guān)于qt tcp 相關(guān)的,

    2024年02月05日
    瀏覽(22)
  • websocket斷線重連&&心跳檢測

    websocket斷線重連&&心跳檢測

    封裝websocket 實(shí)現(xiàn)斷線重連跟心態(tài)檢測,使用的typeScript去封裝 在nodejs 安裝ws庫 代碼如下(示例): ?服務(wù)端實(shí)現(xiàn)ws 創(chuàng)建一個(gè)server.js 文件 運(yùn)行ws服務(wù) ? node .server.js? 客戶端實(shí)現(xiàn)websocket 創(chuàng)建一個(gè)socket.ts 文件 vue 頁面使用 斷開ws服務(wù) 斷線? 啟動(dòng)服務(wù)后 自動(dòng)重連

    2024年01月19日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包