前言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; } }}使用方法Permalinkimport '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/
来源地址:https://blog.csdn.net/shelutai/article/details/132576553