Flutter:WebSocket封装-实现心跳、重连机制

这篇具有很好参考价值的文章主要介绍了Flutter:WebSocket封装-实现心跳、重连机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言Permalink
Flutter简介

Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加 native扩展。同时 Flutter还使用 Native引擎渲染视图,这无疑能为用户提供良好的体验。

WebSocket简介

Http协议是无状态的,只能由客户端主动发起,服务端再被动响应,服务端无法向客户端主动推送内容,并且一旦服务器响应结束,链接就会断开(见注解部分),所以无法进行实时通信。WebSocket协议正是为解决客户端与服务端实时通信而产生的技术,现在已经被主流浏览器支持,所以对于Web开发者来说应该比较熟悉了,Flutter也提供了专门的包来支持WebSocket协议。

注意:Http协议中虽然可以通过keep-alive机制使服务器在响应结束后链接会保持一段时间,但最终还是会断开,keep-alive机制主要是用于避免在同一台服务器请求多个资源时频繁创建链接,它本质上是支持链接复用的技术,而并非用于实时通信,读者需要知道这两者的区别。

WebSocket协议本质上是一个基于tcp的协议,它是先通过HTTP协议发起一条特殊的http请求进行握手后,如果服务端支持WebSocket协议,则会进行协议升级。WebSocket会使用http协议握手后创建的tcp链接,和http协议不同的是,WebSocket的tcp链接是个长链接(不会断开),所以服务端与客户端就可以通过此TCP连接进行实时通信。有关WebSocket协议细节,读者可以看RFC文档,下面我们重点看看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状态
enum SocketStatus {
  SocketStatusConnected, // 已连接
  SocketStatusFailed, // 失败
  SocketStatusClosed, // 连接关闭
}

class WebSocketUtility {
  /// 单例对象
  static WebSocketUtility _socket;

  /// 内部构造方法,可避免外部暴露构造函数,进行实例化
  WebSocketUtility._();

  /// 获取单例内部方法
  factory WebSocketUtility() {
    // 只能有一个实例
    if (_socket == null) {
      _socket = new WebSocketUtility._();
    }
    return _socket;
  }

  IOWebSocketChannel _webSocket; // WebSocket
  SocketStatus _socketStatus; // socket状态
  Timer _heartBeat; // 心跳定时器
  num _heartTimes = 3000; // 心跳间隔(毫秒)
  num _reconnectCount = 60; // 重连次数,默认60次
  num _reconnectTimes = 0; // 重连计数器
  Timer _reconnectTimer; // 重连定时器
  Function onError; // 连接错误回调
  Function onOpen; // 连接开启回调
  Function onMessage; // 接收消息回调

  /// 初始化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实例
    _socketStatus = SocketStatus.SocketStatusConnected;
    // 连接成功,重置重连计数器
    _reconnectTimes = 0;
    if (_reconnectTimer != null) {
      _reconnectTimer.cancel();
      _reconnectTimer = null;
    }
    onOpen();
    // 接收消息
    _webSocket.stream.listen((data) => webSocketOnMessage(data),
        onError: webSocketOnError, onDone: webSocketOnDone);
  }

  /// WebSocket接收消息回调
  webSocketOnMessage(data) {
    onMessage(data);
  }

  /// WebSocket关闭连接回调
  webSocketOnDone() {
    print('closed');
    reconnect();
  }

  /// WebSocket连接错误回调
  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;
    }
  }

  /// 关闭WebSocket
  void closeSocket() {
    if (_webSocket != null) {
      print('WebSocket连接关闭');
      _webSocket.sink.close();
      destroyHeartBeat();
      _socketStatus = SocketStatus.SocketStatusClosed;
    }
  }

  /// 发送WebSocket消息
  void sendMessage(message) {
    if (_webSocket != null) {
      switch (_socketStatus) {
        case SocketStatus.SocketStatusConnected:
          print('发送中:' + message);
          _webSocket.sink.add(message);
          break;
        case SocketStatus.SocketStatusClosed:
          print('连接已关闭');
          break;
        case SocketStatus.SocketStatusFailed:
          print('发送失败');
          break;
        default:
          break;
      }
    }
  }

  /// 重连机制
  void reconnect() {
    if (_reconnectTimes < _reconnectCount) {
      _reconnectTimes++;
      _reconnectTimer =
          new Timer.periodic(Duration(milliseconds: _heartTimes), (timer) {
        openSocket();
      });
    } else {
      if (_reconnectTimer != null) {
        print('重连次数超过最大次数');
        _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);
});

转自: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版本后的代码:文章来源地址https://www.toymoban.com/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状态
enum SocketStatus {
  socketStatusConnected, // 已连接
  socketStatusFailed, // 失败
  socketStatusClosed, // 连接关闭
}

class WebSocketUtility {
  /// 单例对象
  static final WebSocketUtility _socket = WebSocketUtility._internal();

  /// 内部构造方法,可避免外部暴露构造函数,进行实例化
  WebSocketUtility._internal();

  /// 获取单例内部方法
  factory WebSocketUtility() {
    return _socket;
  }

  late WebSocketChannel _webSocket; // WebSocket
  SocketStatus? _socketStatus; // socket状态
  Timer? _heartBeat; // 心跳定时器
  final int _heartTimes = 30000; // 心跳间隔(毫秒)
  final int _reconnectCount = 2; // 重连次数,默认60次
  int _reconnectTimes = 0; // 重连计数器
  Timer? _reconnectTimer; // 重连定时器
  late Function onError; // 连接错误回调
  late Function onOpen; // 连接开启回调
  late Function onMessage; // 接收消息回调



  /// 初始化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实例
    _socketStatus = SocketStatus.socketStatusConnected;
    // 连接成功,重置重连计数器
    _reconnectTimes = 0;
    if (_reconnectTimer != null) {
      _reconnectTimer?.cancel();
      _reconnectTimer = null;
    }
    onOpen();
    // 接收消息
    _webSocket.stream.listen((data) => webSocketOnMessage(data),
        onError: webSocketOnError, onDone: webSocketOnDone);
  }

  /// WebSocket接收消息回调
  webSocketOnMessage(data) {
    onMessage(data);
  }

  /// WebSocket关闭连接回调
  webSocketOnDone() {
    print('webSocketOnDone closed');
    _socketStatus = SocketStatus.socketStatusClosed;
    reconnect();
  }

  /// WebSocket连接错误回调
  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;
    }
  }

  /// 关闭WebSocket
  void closeSocket() {
    print('WebSocket连接关闭');
    _webSocket.sink.close();
    destroyHeartBeat();
    _socketStatus = SocketStatus.socketStatusClosed;
  }

  /// 发送WebSocket消息
  void sendMessage(message) {
    switch (_socketStatus) {
      case SocketStatus.socketStatusConnected:
        print('发送中:$message');
        _webSocket.sink.add(message);
        break;
      case SocketStatus.socketStatusClosed:
        print('连接已关闭');
        break;
      case SocketStatus.socketStatusFailed:
        print('发送失败');
        break;
      default:
        break;
    }
  }

  /// 重连机制
  void reconnect() {
    if (_reconnectTimes < _reconnectCount) {
      _reconnectTimes++;
      _reconnectTimer =
      Timer.periodic(Duration(milliseconds: _heartTimes), (timer) {
        openSocket();
      });
    } else {
      if (_reconnectTimer != null) {
        print('重连次数超过最大次数');
        _reconnectTimer?.cancel();
        _reconnectTimer = null;
      }
      return;
    }
  }

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


}

到了这里,关于Flutter:WebSocket封装-实现心跳、重连机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • websocket的基础使用,心跳机制,断线重连

    websoket出现的原因: 传统的http请求只能是由前端向后台发送一个请求,然后后台把结果返回给前端,前端再进行展示。这里就暴露了一个问题,就是通信只能由前端发起,而后台无法主动与前端通信。而websoket的出现就是为了解决这个问题,让前端可以主动联系后台,后台也

    2024年02月06日
    浏览(48)
  • WebSocket实战之六心跳重连机制

    WebSocket应用部署到生产环境,我们除了会碰到因为经过代理服务器无法连接的问题(注:该问题可以通过搭建WSS来解决,具体配置请看 WebSocket实战之四WSS配置 ),另外一个问题就是外网环境不稳定经常会断开或者服务器重启或者网络中间服务器当发现一个长连接长时间没有

    2024年02月07日
    浏览(48)
  • uniapp使用WebSocket断线,心跳重连机制

    提示:我们在使用WebSocket,经常会遇到有的时候给别人发消息,别人会接收不到,这个时候就有可能是WebSocket断线了,所以这个时候心跳包就出现了 提示:可直接使用,记得把对应地址替换一下

    2024年04月12日
    浏览(42)
  • websocket实时通讯和socket.io实时通信库的使用;心跳机制与断线重连

    https://zh.javascript.info/websocket WebSocket 是一种网络通信协议,就类似于 HTTP 也是一种通信协议。 为什么需要 WebSocket? 因为 HTTP 协议有一个缺陷:通信只能由客户端发起。 代码解析: 创建WebSocket实例:通过 new WebSocket() 创建一个WebSocket实例。在括号中传入服务器的URL,该URL指定了

    2024年02月16日
    浏览(42)
  • vue3使用websocket简易封装,包含错误重连机制

    websocket实现的全双工通信,真真太香了,以下是笔者在使用时,自己封装的一个简易js工具。若需要源码,请移步这里 笔者这里会重连3次,重连的过程给与用户提示,3次之后会提示用户手动刷新 这里与后端约定的数据返回,加上type作为接口判断依据,因此这里不一定通用。

    2024年02月11日
    浏览(47)
  • uni-app 封装 websocket 并且监听心跳机制

    新建 socket.js , 将以下代码复制进去 ,向外暴露。 在入口文件中 将 socketIO 挂载在 Vue 原型上 , 也可以按需引入置顶页面 。 在需要用到webSocket的页面中使用如下方法(可根据自身业务需求进行整改) 离开页面,记得断开连接。

    2024年02月11日
    浏览(46)
  • Vue 2 中 WebSocket 模块实现与应用(包含心跳检测、自动重连)

    WebSocket 技术是一种在 Web 开发中常用的实时通信方式,它允许客户端和服务器之间建立持久性的双向连接,以便实时地传输数据。在 Vue.js 项目中,使用 WebSocket 可以轻松实现实时消息推送、即时通讯等功能。在这篇博客中,我们将介绍一个基于 Vue.js 的 WebSocket 模块的实现,

    2024年02月03日
    浏览(37)
  • WebSocket心跳重连在微信小程序中的实现与服务器端

    WebSocket技术是一种在浏览器和服务器之间建立持久化连接的通信协议。在微信小程序中,通过WebSocket可以实现实时的双向通信。然而,由于网络等各种因素的不稳定性,WebSocket连接可能会出现断开的情况。为了保证连接的可靠性,我们可以通过心跳机制和重连机制来处理Web

    2024年03月18日
    浏览(53)
  • C++ Qt TCP的心跳检测机制,断线重连技术,应用层代码重新实现

    目录 前言: 一、Qt直接启动本身的KeepAlive 二、在应用层自己实现一个心跳检测  三、自定义心跳代码实现: 完整客户端服务端工程下载: 共用的结构体相关头文件:         客户端部分核心代码:         服务端部分核心代码: 运行结果展示: 前两篇关于qt tcp 相关的,

    2024年02月05日
    浏览(44)
  • websocket超时重连、心跳检测

    在单个TCP连接上进行全双工通信的协议,可以实现服务端和客户端双向推送信息的协议。我们在使用webscoket通信时必须要注意的问题超时重连和心跳检测。 超时重连:当出现错误时客户端尝试重新连接websocket。 心跳检测:客户端长时间没接收到服务端消息,就向服务端发送

    2024年02月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包