Flutter SignalR通信插件signalr_netcore_plus的使用

Flutter SignalR通信插件signalr_netcore_plus的使用

pub package

A Flutter SignalR客户端用于 ASP.NET Core
ASP.NET Core SignalR 是一个开源库,简化了向应用添加实时Web功能的过程。实时Web功能使服务器端代码能够即时向客户端推送内容。

该客户端经过测试与 ASP.NET Core 3.1 和 ASP .NET Core 6 兼容。

该客户端能够调用服务器端的Hub函数(包括流式处理函数),并接收由服务器发起的方法调用。它还支持自动重连功能。

该客户端支持以下传输协议:

  • WebSocket
  • Service Side Events
  • Long Polling

该客户端支持以下Hub协议:

  • Json
  • MessagePack

示例

开始使用

pubspec.yaml 文件中添加 signalr_netcore_plus 依赖项:

dependencies:
  flutter:
    sdk: flutter

  signalr_netcore_plus:

重要提示:如果你遇到问题(例如收不到消息回调)与最新版本有关,请尝试使用较旧的版本如 signalr_netcore_plus: 0.1.7+2-nullsafety.3,但请注意,该版本不支持自动重连功能,需要手动处理。

使用方法

让我们演示一些基本用法:

1. 创建Hub连接
// 导入库
import 'package:signalr_netcore_plus/signalr_client.dart';

// SignalR服务器的位置
final serverUrl = "192.168.10.50:51001";
// 使用HubConnectionBuilder创建连接
final hubConnection = HubConnectionBuilder().withUrl(serverUrl).build();
// 当连接关闭时,在控制台打印一条消息
hubConnection.onclose((error) => print("Connection Closed"));

日志记录可以通过 Dart 的 logging包 支持:

// 导入日志库
import 'package:logging/logging.dart';
import 'package:signalr_netcore_plus/signalr_client.dart';

// 配置日志
Logger.root.level = Level.ALL;
// 将日志写入控制台
Logger.root.onRecord.listen((LogRecord rec) {
  print('${rec.level.name}: ${rec.time}: ${rec.message}');
});

// 如果只想记录高级别Hub协议的消息:
final hubProtLogger = Logger("SignalR - hub");
// 如果还想记录传输消息:
final transportProtLogger = Logger("SignalR - transport");

// SignalR服务器的位置
final serverUrl = "192.168.10.50:51001";
final httpOptions = HttpConnectionOptions(logger: transportProtLogger);
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.WebSockets); // 默认传输类型
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.ServerSentEvents);
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.LongPolling);

// 如果需要授权Hub连接,则提供一个异步回调函数,返回令牌字符串(见AccessTokenFactory类型定义)并分配给accessTokenFactory参数:
// final httpOptions = new HttpConnectionOptions(.... accessTokenFactory: () async => await getAccessToken());

// 使用HubConnectionBuilder创建连接
final hubConnection = HubConnectionBuilder().withUrl(serverUrl, options: httpOptions).configureLogging(hubProtLogger).build();
// 当连接关闭时,在控制台打印一条消息
hubConnection.onclose((error) => print("Connection Closed"));
2. 连接到Hub

调用以下方法开始握手并连接客户端到SignalR服务器

await hubConnection.start();
3. 调用Hub函数

假设有一个这样的Hub函数:

public string MethodOneSimpleParameterSimpleReturnValue(string p1)
{
  Console.WriteLine($"'MethodOneSimpleParameterSimpleReturnValue' invoked. Parameter value: '{p1}");
  return p1;
}

客户端可以使用以下方式调用该函数:

final result = await hubConnection.invoke("MethodOneSimpleParameterSimpleReturnValue", args: <Object>["ParameterValue"]);
logger.log(LogLevel.Information, "Result: '$result'");
4. 调用客户端函数

假设服务器调用了一个名为 “aClientProvidedFunction” 的函数:

await Clients.Caller.SendAsync("aClientProvidedFunction", null);

客户端提供该函数的方式如下:

hubConnection.on("aClientProvidedFunction", _handleAClientProvidedFunction);

// 注销函数
// a) 注销特定实现:
// hubConnection.off("aClientProvidedFunction", method: _handleServerInvokeMethodNoParametersNoReturnValue);
// b) 注销所有实现:
// hubConnection.off("aClientProvidedFunction");

...

void _handleAClientProvidedFunction(List<Object> parameters) {
  logger.log(LogLevel.Information, "Server invoked the method");
}
5. 使用Msgpack进行序列化

Hub应在客户端和服务器上配置为使用Msgpack协议

客户端
import 'package:signalr_netcore_plus/msgpack_hub_protocol.dart';
_hubConnection = HubConnectionBuilder()
          .withUrl(_serverUrl, options: httpOptions)
          /* 配置Hub使用Msgpack协议 */
          .withHubProtocol(MessagePackHubProtocol())
          .withAutomaticReconnect()
          .configureLogging(logger)
          .withSingleListener(true)
          .build();
服务器

在你的ASP NET核心项目中添加以下包 Microsoft.AspNetCore.SignalR.Protocols.MessagePack

public void ConfigureServices(IServiceCollection services)
        {
            // 配置Hub使用Msgpack协议
            services.AddSignalR().AddMessagePackProtocol();

        }
关于参数类型的注意事项

所有函数参数和返回值都通过使用dart:convert包(json.endcode/json.decode)进行序列化/反序列化。确保你:

  • 只使用简单参数类型
  • 或者
  • 使用实现了toJson()方法的对象,因为该方法被dart:convert包用来序列化对象。

Flutter Json 101:

MSGPACK

所有函数参数和返回值都通过使用 msgpack_dart 包进行序列化/反序列化。确保你:

  • 只使用简单参数类型
  • 或者
  • 将类转换为Map,并使用Json编码/解码后传递给Msgpack
  • 或者
  • 使用自定义编码器和解码器将消息序列化为字节,然后传递给SignalR
MSGPACK - 它像JSON一样,但更快更小
如何暴露一个MessageHeaders对象以便客户端可以发送默认头部

代码示例:

final defaultHeaders = MessageHeaders();
defaultHeaders.setHeaderValue("HEADER_MOCK_1", "HEADER_VALUE_1");
defaultHeaders.setHeaderValue("HEADER_MOCK_2", "HEADER_VALUE_2");

final httpConnectionOptions = new HttpConnectionOptions(
          httpClient: WebSupportingHttpClient(logger,
              httpClientCreateCallback: _httpClientCreateCallback),
          accessTokenFactory: () => Future.value('JWT_TOKEN'),
          logger: logger,
          logMessageContent: true,
          headers: defaultHeaders);

final _hubConnection = HubConnectionBuilder()
          .withUrl(_serverUrl, options: httpConnectionOptions)
          .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000, null])
          .configureLogging(logger)
          .withSingleListener(true)
          .build();

HTTP请求日志:

I/flutter ( 5248): Starting connection with transfer format 'TransferFormat.Text'.
I/flutter ( 5248): Sending negotiation request: https://localhost:5000/negotiate?negotiateVersion=1
I/flutter ( 5248): HTTP send: url 'https://localhost:5000/negotiate?negotiateVersion=1', method: 'POST' content: '' content length = '0' 
headers: '{ content-type: text/plain;charset=UTF-8 }, { HEADER_MOCK_1: HEADER_VALUE_1 }, { X-Requested-With: FlutterHttpClient }, { HEADER_MOCK_2: HEADER_VALUE_2 }, { Authorization: Bearer JWT_TOKEN }'

示例代码

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

const kChatServerUrl = "http://192.168.0.4:5000";

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

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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用signalr_netcore_plus插件进行SignalR通信的示例代码。signalr_netcore_plus是一个用于Flutter的SignalR客户端库,允许你与ASP.NET Core SignalR服务器进行通信。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加signalr_netcore_plus依赖:

dependencies:
  flutter:
    sdk: flutter
  signalr_netcore_plus: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来获取依赖。

2. 配置SignalR连接

在你的Flutter项目中,创建一个新的Dart文件(例如signalr_service.dart)来配置和管理SignalR连接。

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

class SignalRService {
  late HubConnection _hubConnection;

  SignalRService() {
    _initSignalR();
  }

  void _initSignalR() async {
    _hubConnection = HubConnectionBuilder()
        .withUrl('https://your-signalr-server-url/your-hub-endpoint')
        .withAutomaticReconnect()
        .build();

    _hubConnection.onclose((error) async {
      print('Connection closed with error: ${error?.message}');
      await startConnection();
    });

    await startConnection();
  }

  Future<void> startConnection() async {
    try {
      await _hubConnection.start();
      print('Connected to SignalR server');
    } catch (e) {
      print('Error while connecting to SignalR server: $e');
    }
  }

  Future<void> sendMessage(String message) async {
    if (_hubConnection.state == HubConnectionState.connected) {
      await _hubConnection.invoke('SendMessage', message);
    } else {
      print('Not connected to SignalR server');
    }
  }

  Stream<String> onReceiveMessage() {
    return _hubConnection.on<String>('ReceiveMessage');
  }
}

3. 使用SignalR服务

在你的Flutter UI中,使用SignalRService来处理SignalR通信。以下是一个简单的示例,展示如何发送和接收消息。

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

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

class MyApp extends StatelessWidget {
  final SignalRService signalRService = SignalRService();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter SignalR Demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextField(
                decoration: InputDecoration(labelText: 'Message'),
                onSubmitted: (message) {
                  signalRService.sendMessage(message);
                },
              ),
              SizedBox(height: 16),
              Expanded(
                child: StreamBuilder<String>(
                  stream: signalRService.onReceiveMessage(),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return Text(
                        'Received: ${snapshot.data!}',
                        style: TextStyle(fontSize: 18),
                      );
                    } else if (snapshot.hasError) {
                      return Text('Error: ${snapshot.error!}');
                    }
                    return Center(child: CircularProgressIndicator());
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

4. 运行应用

确保你的ASP.NET Core SignalR服务器正在运行,并且URL和Hub名称与代码中配置的相匹配。然后运行你的Flutter应用,你应该能够通过UI发送消息到服务器,并接收来自服务器的消息。

这个示例展示了如何使用signalr_netcore_plus插件在Flutter应用中建立和管理SignalR连接,发送和接收消息。根据你的实际需求,你可以进一步扩展和定制这个示例。

回到顶部