• Flutter学习笔记 —— WebSocket篇


    Flutter学习笔记 —— WebSocket

    在这里插入图片描述

    前言

    WebSocket 大家都不陌生了,我们今天来看看怎么在Flutter中使用WebSocket!

    开发环境

    • Android Studio
    • Android SDK API 33

    Flutter 安装插件

    web_socket_channel: ^2.2.0
    

    正文

    我们使用 WebSocket库来进行WebSocket的相关操作

    一、连接

    使用该库的连接方法为以下方式

    IOWebSocketChannel ioWebSocketChannel = IOWebSocketChannel.connect("ws://ip:端口/ws");
    

    连接成功后,我们下一步就是进行监听Socket消息

    ListenerStream(监听Socket消息)

    以下是监听Socket消息方式

    ioWebSocketChannel.stream.listen((data){
        //消息
    }));
    

    值得一提的是监听方式不但可以监听消息,还可以监听异常和Socket连接是否结束

    以下是代码示例

    ioWebSocketChannel.stream.listen((event) { 
             
           },onDone: (){
             //结束!
           },onError: (){
             //异常!
        });
    

    我们知道,当Socket服务一定时间内没收到消息则会认为超时,那么我们应该发送心跳包,接下来会逐步介绍

    SendMessage(发送Socket消息)
    

    发送Socket消息也非常简单,请看代码示例

    ioWebSocketChannel.sink.add("消息");
    

    add(T) 可以发送的消息是一个泛型,意味着你可以发送不同的消息至服务器

    四、发送心跳包

    什么是心跳包呢?简述概括就是:

    当Socket服务一定时间没有收到消息则会自动断连,那么此时我们要做的就是一定时间内发送心跳消息至Socket服务,让服务认为客户端还活着,从而继续工作!

    我们从中可以得到一些关键字的消息

    一定时间发送消息至服务器

    第一时间我们想到的就是定时器(Timer) 当然如果你想用Future的延迟也是可以的!

    说了那么多,我们看看如何实现!

    定义计时器方法

      /**
       * 发送心跳包
       */
      static void sendHeartPacket(){
        Map<String,dynamic> data = {
          "code": 9999,
          "msg": "心跳包",
        };
        var jsonData = json.encode(data);
        IOWebSocketChannel.sink.add(jsonData);
      }
    

    我们定义了一个基础的发包方法,那我们接下来需要处理的就是,在一定时间内发心跳包到服务器,如果心跳包发成功了,那么我们应该重新连接

    发送心跳包

      /**
       * @desc WebSocket心跳包
       * @author Marinda
       * @date 2022/9/26
       */
      static void heartPacket(){
    
          //自定义Bool,判断是否Socket开启状态
         if(state.socketStatus){
    
          //自定义重连时间间隔
           hearTimer = Timer(Duration(seconds: state.socketClienTime),() async{
           //  重新连接
             reconnectSocket();
           });
           sendHeartPacket();
         }
      }
    
    

    断开连接

      /**
       * 销毁心跳包
       */
      static void destoryHeart(){
         //为心跳包则直接
         if(state.heartStatus){
            hearTimer?.cancel();
            state.heartStatus = false;
         }
      }
    

    重新连接

      /**
       * 重新连接socket
       */
      static void reconnectSocket(){
         destoryHeart();
         connectSocket();
      }
    

    代码示例

    import 'dart:async';
    import 'package:dio/dio.dart';
    import 'package:web_socket_channel/io.dart';
    import 'package:web_socket_channel/web_socket_channel.dart';
    import 'State.dart';
    import 'dart:convert';
    
    import 'Result.dart';
    /**
     * @date 2022/9/26
     * @author Marinda
     * @desc websocket的实现
     */
    class WebSocketHandle {
      static WebSocketState state = WebSocketState();
      static late Timer hearTimer;
      WebSocketHandle();
    
       static void connectSocket() async {
           await closeSocket();
           String socketUrl = state.socketUrl;
           LoggerUtil.logger.i("发起WebSocket请求,地址为:${socketUrl}");
           state.webSocket = IOWebSocketChannel.connect(socketUrl);
    
           state.socketStatus = true;
           initConnectSocket();
      }
    
      static void initConnectSocket(){
        WebSocketHandle.onMessageListener();
        heartPacket();
      }
    
      /**
       * @desc 校验连接配置是否重复
       * @author Marinda
       * @date 2022/9/27
       */
      static bool validConnection(String ip,int port){
         return state.ip == ip && state.port == port ? true : false;
      }
      /**
       * @desc WebSocket消息监听器
       * @author Marinda
       * @date 2022/9/26
       */
      static void onMessageListener(){
    
         WebSocketResult webSocketResult = WebSocketResult();
         state.webSocket?.stream.listen((data){
          var jsonData = json.decode(data);
          if(jsonData is Map<String,dynamic>){
            //检测到心跳包
            if(jsonData['code'] == 9999){
            //  不处理
            }else{
              Map<String,dynamic> mapData = jsonData['data'];
              webSocketResult = WebSocketResult.fromJson(mapData);
                state.webSocketResult = webSocketResult;
                LoggerUtil.logger.i("监听到服务端Socket返回数据:                   ${state.webSocketResult.toString()}");   
    },onError: (e){
          state.socketStatus = false;
          state.isError = true;
        },onDone: (){
          state.socketStatus = false;
        });
      }
    
      /**
       * 销毁心跳包
       */
      static void destoryHeart(){
         //为心跳包则直接
         if(state.heartStatus){
            hearTimer?.cancel();
            state.heartStatus = false;
         }
      }
    
      /**
       * 发送心跳包
       */
      static void sendHeartPacket(){
        Map<String,dynamic> data = {
          "code": 9999,
          "msg": "心跳包",
        };
        var jsonData = json.encode(data);
        state.webSocket?.sink.add(jsonData);
        state.heartStatus = true;
      }
    
      /**
       * @desc WebSocket心跳包
       * @author Marinda
       * @date 2022/9/26
       */
      static void heartPacket(){
         if(state.socketStatus){
           hearTimer = Timer(Duration(seconds: state.socketClienTime),() async{
           //  重新连接
             reconnectSocket();
           });
           sendHeartPacket();
         }
      }
    
      /**
       * 重新连接socket
       */
      static void reconnectSocket(){
         destoryHeart();
         connectSocket();
      }
    
      /**
       * @desc 关闭WebSocket
       * @author Marinda
       * @date 2022/9/26
       */
      static Future closeSocket() async{
         if(state.webSocket != null){
           state.webSocket?.sink.close();
           state.webSocket = null;
           state.socketStatus = false;
         }
      }
    
    }
    

    结束

    至此笔记到此结束,感谢你的观看!

  • 相关阅读:
    展示用HTML编写的个人简历信息
    【设计模式】Java设计模式 - 策略模式
    Ubuntu18.04运行gazebo的launch文件[model-4] process has died报错
    IDEA 新建 JavaWeb 项目(:找不到 Web Application 解决方法)
    Qt+Python多次刷新缓存的问题及项目延伸:
    【深度学习实验】前馈神经网络(六):自动求导
    多线程并发之CountDownLatch阻塞等待
    Unity中Shader光强与环境色
    Hexagon_V65_Programmers_Reference_Manual(33)
    rt-thread 之------fal移植
  • 原文地址:https://blog.csdn.net/qq_33638188/article/details/127106389