Flutter WebSocket通信插件websocket_universal的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter WebSocket通信插件websocket_universal的使用

websocket_universal 是一个为Dart和Flutter设计的WebSocket客户端库,支持所有平台(web、移动、桌面)。它提供了一个易于使用的接口来处理WebSocket通信,并且包含了一些实用的功能,如自动重连、Ping延迟测量等。以下是关于如何使用这个插件的详细介绍。

快速开始

import 'package:websocket_universal/websocket_universal.dart';

void main() async {
  final textSocketHandler = IWebSocketHandler<String, String>.createClient(
    'wss://ws.postman-echo.com/raw', // Postman echo ws server
    SocketSimpleTextProcessor(),
  );

  textSocketHandler.incomingMessagesStream.listen((inMsg) {
    print('> webSocket got text message from server: "$inMsg" '
        '[ping: ${textSocketHandler.pingDelayMs}]');
  });
  textSocketHandler.outgoingMessagesStream.listen((inMsg) {
    print('> webSocket sent text message to   server: "$inMsg" '
        '[ping: ${textSocketHandler.pingDelayMs}]');
  });

  await textSocketHandler.connect();
  textSocketHandler.sendMessage('Hello server!');
  await Future<void>.delayed(const Duration(seconds: 4));

  await textSocketHandler.disconnect('manual disconnect');
  textSocketHandler.close();
}

示例1:简单的字符串消息交换

描述

此示例展示了如何与服务器进行简单的字符串消息交换。我们使用了Postman Echo Server作为示例服务器。

import 'package:websocket_universal/websocket_universal.dart';

void main() async {
  const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
  const textMessageToServer = 'Hello server!';
  const connectionOptions = SocketConnectionOptions(
    pingIntervalMs: 3000,
    timeoutConnectionMs: 4000,
    skipPingMessages: false,
  );

  final IMessageProcessor<String, String> textSocketProcessor =
      SocketSimpleTextProcessor();
  final textSocketHandler = IWebSocketHandler<String, String>.createClient(
    websocketConnectionUri,
    textSocketProcessor,
    connectionOptions: connectionOptions,
  );

  textSocketHandler.socketHandlerStateStream.listen((stateEvent) {
    print('> status changed to ${stateEvent.status}');
  });

  textSocketHandler.incomingMessagesStream.listen((inMsg) {
    print('> webSocket got text message from server: "$inMsg" '
        '[ping: ${textSocketHandler.pingDelayMs}]');
  });

  textSocketHandler.logEventStream.listen((debugEvent) {
    print('> debug event: ${debugEvent.socketLogEventType}'
        ' [ping=${debugEvent.pingMs} ms]. Debug message=${debugEvent.message}');
  });

  textSocketHandler.outgoingMessagesStream.listen((inMsg) {
    print('> webSocket sent text message to   server: "$inMsg" '
        '[ping: ${textSocketHandler.pingDelayMs}]');
  });

  final isTextSocketConnected = await textSocketHandler.connect();
  if (!isTextSocketConnected) {
    print('Connection to [$websocketConnectionUri] failed for some reason!');
    return;
  }

  textSocketHandler.sendMessage(textMessageToServer);

  await Future<void>.delayed(const Duration(seconds: 30));
  await textSocketHandler.disconnect('manual disconnect');
  textSocketHandler.close();
}

示例2:推荐的方式 - 使用类型化的消息

描述

在实际应用中,推荐使用类型化消息来确保数据的一致性和可读性。下面是一个使用 ISocketMessageIMessageToServer 接口的例子。

import 'package:websocket_universal/websocket_universal.dart';

void main() async {
  const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
  const textMessageToServer = 'Hello server!';
  const connectionOptions = SocketConnectionOptions(
    pingIntervalMs: 3000,
    timeoutConnectionMs: 4000,
    skipPingMessages: false,
  );

  final IMessageProcessor<ISocketMessage<Object?>, IMessageToServer>
      messageProcessor = SocketMessageProcessor();
  final socketHandler =
      IWebSocketHandler<ISocketMessage<Object?>, IMessageToServer>.createClient(
    websocketConnectionUri,
    messageProcessor,
    connectionOptions: connectionOptions,
  );

  socketHandler.logEventStream.listen((debugEvent) {
    print('> debug event: ${debugEvent.socketLogEventType}'
        ' ping=${debugEvent.pingMs} ms. Debug message=${debugEvent.message}');
  });

  socketHandler.socketStateStream.listen((stateEvent) {
    print('> status changed to ${stateEvent.status}');
  });

  const messageTypeStr = '[ISocketMessage]';
  socketHandler.incomingMessagesStream.listen((inMsg) {
    print('> webSocket got $messageTypeStr: $inMsg');
  });

  socketHandler.outgoingMessagesStream.listen((inMsg) {
    print('> webSocket sent $messageTypeStr: $inMsg');
  });

  final isConnected = await socketHandler.connect();

  if (!isConnected) {
    print('Connection to [$websocketConnectionUri] failed for some reason!');
    return;
  }

  final outMsg = MessageToServerImpl.onlyHost(
    host: 'test',
    data: '{"payload": "$textMessageToServer"}',
    error: null,
  );
  socketHandler.sendMessage(outMsg);

  await Future<void>.delayed(const Duration(seconds: 8));
  await socketHandler.disconnect('manual disconnect');
  socketHandler.close();
}

示例3:处理字节消息

描述

当需要发送或接收字节数组时,可以使用 SocketSimpleBytesProcessor 来处理二进制数据。

import 'dart:convert';
import 'package:websocket_universal/websocket_universal.dart';

void main() async {
  const websocketLocalExample = 'ws://127.0.0.1:42627/websocket';
  const textMessageToServer = 'Hello server!';
  const connectionOptions = SocketConnectionOptions(
    pingIntervalMs: 3000,
    timeoutConnectionMs: 4000,
    skipPingMessages: false,
  );

  final IMessageProcessor<List<int>, List<int>> bytesSocketProcessor =
      SocketSimpleBytesProcessor();
  final bytesSocketHandler =
      IWebSocketHandler<List<int>, List<int>>.createClient(
    websocketLocalExample,
    bytesSocketProcessor,
    connectionOptions: connectionOptions,
  );

  bytesSocketHandler.logEventStream.listen((debugEvent) {
    print('> debug event: ${debugEvent.socketLogEventType}'
        ' ping=${debugEvent.pingMs} ms. Debug message=${debugEvent.message}');
  });

  bytesSocketHandler.incomingMessagesStream.listen((inMsg) {
    print('> webSocket got bytes message from server: "$inMsg"');
  });

  bytesSocketHandler.outgoingMessagesStream.listen((inMsg) {
    print('> webSocket sent bytes message to   server: "$inMsg"');
  });

  final isBytesSocketConnected = await bytesSocketHandler.connect();
  if (!isBytesSocketConnected) {
    print('Connection to [$websocketLocalExample] for bytesSocketHandler '
        'failed for some reason!');
    return;
  }

  final bytesMessage = utf8.encode(textMessageToServer);
  bytesSocketHandler.sendMessage(bytesMessage);

  await Future<void>.delayed(const Duration(seconds: 7));
  await bytesSocketHandler.disconnect('manual disconnect');
  bytesSocketHandler.close();
}

示例4:高级 ISocketMessage 处理 - 组合服务器响应

描述

此示例展示了如何创建更复杂的请求并处理来自服务器的组合响应。

import 'dart:convert';
import 'package:websocket_universal/websocket_universal.dart';

void main() async {
  const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
  const connectionOptions = SocketConnectionOptions(
    pingIntervalMs: 3000,
    timeoutConnectionMs: 4000,
    skipPingMessages: false,
  );

  final IMessageProcessor<ISocketMessage<Object?>, IMessageToServer>
      messageProcessor = SocketMessageProcessor();
  final socketHandler =
      IWebSocketHandler<ISocketMessage<Object?>, IMessageToServer>.createClient(
    websocketConnectionUri,
    messageProcessor,
    connectionOptions: connectionOptions,
  );

  final ISocketManagerMiddleware middleware = SocketManagerMiddleware();
  final IWebSocketRequestManager requestManager = WebSocketRequestManager(
    middleware: middleware,
    webSocketHandler: socketHandler,
  );
  final IWebSocketDataBridge dataBridge = WebSocketDataBridge(requestManager);

  final isConnected = await socketHandler.connect();

  if (!isConnected) {
    print('Connection to [$websocketConnectionUri] failed for some reason!');
    return;
  }

  final requestGame = MessageToServerImpl.duo(
    host: TestDecoder.host,
    topic1: CustomGameModel.topic1,
    data: jsonEncode(
      const CustomGameModel(
        name: 'MakeWorld strategy',
        playersAmount: 8,
      ),
    ),
    error: null,
  );
  final socketRequest = SocketRequest(requestMessage: requestGame);

  final result =
      await dataBridge.singleRequestFull<CustomGameModel>(socketRequest);
  print('Got result: ${result.data}');

  final outMsgList = MessageToServerImpl.duo(
    host: TestDecoder.host,
    topic1: CustomGameModel.topic1List,
    data: jsonEncode([
      const CustomGameModel(
        name: 'MakeWorld strategy',
        playersAmount: 8,
      ),
      const CustomGameModel(
        name: 'New patch',
        playersAmount: 4,
      ),
    ]),
    error: null,
  );
  final socketRequestList = SocketRequest(requestMessage: outMsgList);

  final listResult = await dataBridge
      .singleRequestFull<List<CustomGameModel>>(socketRequestList);
  print('Got list result: ${listResult.data}');

  final topicSingle = SocketTopicImpl.duo(
    host: TestDecoder.host,
    topic1: CustomGameModel.topic1,
  );
  final topicList = SocketTopicImpl.duo(
    host: TestDecoder.host,
    topic1: CustomGameModel.topic1List,
  );

  final compositeRequest = SocketRequest(
    requestMessage: requestGame,
    responseTopics: {topicSingle, topicList},
  );

  final compositeTask = dataBridge.compositeRequest(compositeRequest);
  dataBridge.requestData(socketRequestList);
  final compositeResp = await compositeTask;

  final responseOne = compositeResp.getData<CustomGameModel>();
  final responseTwo = compositeResp.getData<List<CustomGameModel>>();

  print('Got composite result. Answers = ${compositeResp.dataCached.length}'
      '[$responseOne] and [$responseTwo]');

  await socketHandler.disconnect('manual disconnect');
  requestManager.close();
  socketHandler.close();
}

通过以上几个示例,您可以了解如何使用 websocket_universal 插件来实现不同类型的WebSocket通信。根据您的需求选择合适的方式来处理消息,以确保应用程序的稳定性和高效性。


更多关于Flutter WebSocket通信插件websocket_universal的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter WebSocket通信插件websocket_universal的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用websocket_universal插件来实现WebSocket通信的代码示例。这个插件允许你通过WebSocket协议与服务器进行通信。

首先,确保你已经在pubspec.yaml文件中添加了websocket_universal依赖:

dependencies:
  flutter:
    sdk: flutter
  websocket_universal: ^2.0.1  # 请注意版本号,根据实际情况调整

然后运行flutter pub get来安装依赖。

接下来,你可以按照以下步骤在Flutter应用中使用WebSocket通信:

1. 导入必要的包

在你的Dart文件中导入websocket_universal包:

import 'package:websocket_universal/websocket_universal.dart';

2. 创建WebSocket连接

你可以使用WebSocketUniversal类来创建一个WebSocket连接。下面是一个简单的示例,展示了如何连接到WebSocket服务器、发送消息和接收消息。

import 'package:flutter/material.dart';
import 'package:websocket_universal/websocket_universal.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  WebSocketUniversal? _webSocket;
  TextEditingController _controller = TextEditingController();
  List<String> _messages = [];

  @override
  void initState() {
    super.initState();
    connectToWebSocket();
  }

  void connectToWebSocket() {
    _webSocket = WebSocketUniversal(
      Uri.parse('wss://your-websocket-server-url'),  // 替换为你的WebSocket服务器URL
      protocols: [],
      headers: {},
    );

    _webSocket!.onOpen = (dynamic data) {
      print('WebSocket connected');
      _messages.add('Connected to WebSocket server');
      setState(() {});
    };

    _webSocket!.onMessage = (dynamic data) {
      print('Received message: ${data.toString()}');
      _messages.add('Received: ${data.toString()}');
      setState(() {});
    };

    _webSocket!.onClose = (dynamic data) {
      print('WebSocket closed');
      _messages.add('Disconnected from WebSocket server');
      setState(() {});
    };

    _webSocket!.onError = (dynamic error) {
      print('WebSocket error: $error');
      _messages.add('Error: $error');
      setState(() {});
    };

    _webSocket!.connect();
  }

  void sendMessage() {
    if (_webSocket!.readyState == WebSocketReadyState.OPEN) {
      _webSocket!.send(_controller.text);
      _messages.add('Sent: ${_controller.text}');
      _controller.clear();
      setState(() {});
    } else {
      _messages.add('WebSocket is not open');
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('WebSocket Demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Expanded(
                child: ListView.builder(
                  itemCount: _messages.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(_messages[index]),
                    );
                  },
                ),
              ),
              TextField(
                controller: _controller,
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  labelText: 'Send Message',
                ),
              ),
              ElevatedButton(
                onPressed: sendMessage,
                child: Text('Send'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _webSocket?.close();
    _controller.dispose();
    super.dispose();
  }
}

3. 运行应用

保存上述代码并运行你的Flutter应用。你应该能够看到一个简单的界面,允许你连接到WebSocket服务器、发送消息并接收服务器的响应。

注意事项

  • 请确保WebSocket服务器的URL是正确的,并且服务器正在运行。
  • 在生产环境中,请处理更多的错误情况和连接管理,例如重连逻辑。
  • 根据需要调整WebSocket的头部信息和协议。

希望这个示例能帮助你理解如何在Flutter应用中使用websocket_universal插件进行WebSocket通信。

回到顶部