socket
注意:
Http 协议中虽然可以通过keep-alive机制使服务器在响应结束后链接会保持一段时间,但最终还是会断开,keep-alive机制主要是用于避免在同一台服务器请求多个资源时频繁创建链接,它本质上是支持链接复用的技术,而并非用于实时通信,读者需要知道这两者的区别。
WebSocket
协议本质上是一个基于tcp
的协议,它是先通过HTTP协议发起一条特殊的 http 请求进行握手后,如果服务端支持WebSocket
协议,则会进行协议升级。WebSocket
会使用 http 协议握手后创建的 tcp 链接,和 http 协议不同的是,WebSocket
的 tcp 链接是个长链接(不会断开),所以服务端与客户端就可以通过此 TCP 连接进行实时通信。
连接到由websocket.org提供的测试服务器。服务器将简单地返回我们发送给它的相同消息!
1、 socket基本使用步骤
1.1 在 pubspec.yaml
包文件中添加包文件名,并通过 flutter package get
下载包依赖
web_socket_channel: ^1.1.0
1.2 在需要使用 socket
的组件中引入包依赖文件
import 'package:web_socket_channel/io.dart';
1.3 连接到``WebSocket` 服务器
// 创建一个 WebSocketChannel 连接到 socket 服务器( ws://echo.websocket.org 是 websocket.org 提供的测试服务器)
IOWebSocketChannel channel = IOWebSocketChannel.connect('ws://echo.websocket.org');
1.4 监听来自服务器的消息
WebSocketChannel
提供了一个来自服务器的消息 Stream
,它是一个异步的基础类,提供了一种方法来监听来自数据源的异步事件,StreamBuilder
组件将连接到一个Stream
, 并在每次收到消息时通知Flutter重新构建界面。
// StreamBuilder 组件监听消息
new StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
print('socket接收的数据格式$snapshot');
print('判断socket是否有数据${snapshot.hasData}');
print('socket数据${snapshot.data}');
return new Text(snapshot.hasData ? '${snapshot.data}' : '');
}
)
1.5 将数据发送到服务器
将数据发送到服务器,测试服务器会给我们发送的数据
channel.sink.add('测试socket发送数据');
1.6 关闭 WebSocket
连接
// 组件销毁的时候关闭 socket 连接
@override
void dispose(){
super.dispose();
// 关闭socket连接
channel.sink.close();
}
2、 socket
提取公共文件封装
2.1 lib
文件夹下新增 socket
文件夹,再 socket
文件夹下再建一个 socket.dart
文件
2.2 socket.dart
文件中封装 socket
// 引入依赖包
import 'package:flutter/cupertino.dart'; // 使用 debugPrint 引入的包
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
class SocketMessage{
WebSocketChannel channel;
// 创建一个WebSocketChannel,并连接到WebSocket服务器
void initSocket(){
print('初始化');
channel = new IOWebSocketChannel.connect('ws://echo.websocket.org');
sendMessage();
// 发送数据给 socket 测试服务器,为了能够收到测试服务器返回的数据(正常情况下不需要)
channel.sink.add('发送测试消息');
}
// 监听socket服务器的状态,并对 成功、异常、断开 进行处理
void sendMessage() {
print('重连');
channel.stream.listen(onData,onError: onError, onDone: onDone );
}
// socket 链接断开以后重新初始化 socket
void onDone()async{
debugPrint("Socket is closed");
initSocket();
}
// socket err 情况的处理
void onError(err){
debugPrint(err.runtimeType.toString());
WebSocketChannelException ex = err;
debugPrint(ex.message);
}
// 收到服务端推送的消息event
void onData(event){
print('收到消息:$event');
// channel.sink.add('aaaa'); // 发送消息给服务器(服务端需要再收到消息时回馈消息给服务端时菜蔬用,否在不需要)
}
// 关闭WebSocket连接
void dispose() {
print('关闭');
channel.sink.close();
}
}
2.3 在需要使用的组件中引入 socket.dart
文件
// 引入封装的 socket.dart 文件
import 'package:项目名/socket/socket.dart';
// 在 initState 中初始化
void initState(){
super.initState();
// 初始化socket
SocketMessage().initSocket();
}
// 在组件销毁时,关闭WebSocket连接
void dispose(){
super.dispse();
// 关闭WebSocket连接
SocketMessage().dispose();
}
注意: 此处并没有对接收到的数据进行存取处理,可以通过 本地存储
、Provider存储
、或者EventBus
处理,在相应的组件中可以直接拿到推送的消息
3、socket
提取公共文件封装 + EventBus
监听获取数据
3.1 在 pubspec.yaml
包文件中添加包文件名,并通过 flutter package get
下载包依赖
event_bus: ^1.1.1
3.2 在需要使用 eventBus
的组件中引入包依赖文件
import 'package:event_bus/event_bus.dart';
3.3 通常封装一个 eventBus
事件总线的文件 event_bus.dart
// 引入 eventBus 包文件
import 'package:event_bus/event_bus.dart';
// 创建EventBus
EventBus eventBus = new EventBus();
// event 监听 socket 接收数据
class EventSocket{
// 想要接收的数据时什么类型的,就定义相同类型的变量
dynamic obj;
EventSocket(this.obj);
}
3.4 socket + eventBus
事件,监听 socket
推送的消息到指定组件中
socket封装部分:
// 引入包文件
import 'package:flutter/cupertino.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:new_flutter/utils/event_bus.dart';
class SocketMessage{
WebSocketChannel channel;
// 创建一个WebSocketChannel,并连接到WebSocket服务器
void initSocket(){
print('初始化 socket');
channel = new IOWebSocketChannel.connect('ws://echo.websocket.org');
sendMessage();
// 发送数据给 socket 测试服务器,为了能够收到测试服务器返回的数据(一般不需要)
channel.sink.add('发送测试消息');
}
// 将数据发送到服务器
void sendMessage() {
print('重连');
channel.stream.listen(onData,onError: onError, onDone: onDone );
}
// socket 链接断开以后重新初始化 socket
void onDone()async{
debugPrint("Socket is closed");
initSocket();
}
// socket err 情况的处理
void onError(err){
debugPrint(err.runtimeType.toString());
WebSocketChannelException ex = err;
debugPrint(ex.message);
}
// 收到服务端推送的消息event
void onData(event){
print('收到消息:$event');
// eventBus 发送event_bus.dart文件中的定义的事件,参数传递事件定义中变量的类型即可
eventBus.fire(EventSocket({
'a':'b',
'c':'e'
}));
}
// 关闭WebSocket连接
void dispose() {
print('关闭');
channel.sink.close();
}
}
eventBus监听、销毁处理:
// 定义变量接收 eventBus 监听实例
var eventBusSocket;
@override
void initState(){
super.initState();
// 初始化socket
SocketMessage().initSocket();
// 注册监听器,订阅 eventbus
eventBusSocket = eventBus.on<EventSocket>().listen((event) {
// event为 event.obj 即为 eventBus.dart 文件中定义的 EventSocket类中监听的数据
print(event.obj);
});
}
@override
void dispose(){
super.dispose();
// 取消订阅
eventBusSocket.cancel();
}