SignalR 的使用

概念

SignalR 可以实现实时的 Web 功能,使服务端可以实时的向客户端传输数据

官网介绍

使用场景

  • 需要从服务器进行高频率更新的应用。比如游戏、社交网络等
  • 需要通知的应用。比如邮件应用、聊天等
  • Dashboard,数据需要实时更新等

通信方式

  • WebSockets
  • Server-Sent Events
  • Long Polling

使用

需要两个角色:Server 和 Client

Server

SignalR 是集成在 AspNetCore 中的,所以不用添加单独的包,可以直接使用

SignalR 有五种使用模式,如下:

  • Client 调用 Server,无返回值

  • Client 调用 Server,有返回值

  • Server 调用 Client 监听的方法(可能存在多个 client,分下面五种情况)

    • 哪个 client 调的 server,server 就调哪个 client

      Clients.Caller.SendAsync

    • 调用所有的 client

      Clients.All.SendAsync

    • 调用除自身(调用 server 的 client)以外的所有 client

      Clients.Others.SendAsync

    • 分组发送(调用指定组的所有 client)

      Groups.AddToGroupAsync
      Clients.Group(${groupName}).SendAsync

    • 调用指定的 client

      Clients.Client(${connId}).SendAsync

  • server 通过流的方式向 client 发送数据

    // 发送流
    public async Task<ChannelReader> SendStream()
    {
    Console.WriteLine("服务端通过流的方式向客户端发送信息");
    var channel = Channel.CreateUnbounded();
    await Task.Run(async () =>
    {
    var list = await File.ReadAllLinesAsync("001.txt");
    foreach (var line in list)
    {
    await channel.Writer.WriteAsync(line);
    }
    });
    return channel;
    }

    // 接收流
    public async Task ReceiveClientMsgByStream(ChannelReader reader)
    {
    Console.WriteLine("接收客户端通过流发来的信息");
    await Task.Run(async () =>
    {
    while (await reader.WaitToReadAsync())
    {
    while (reader.TryRead(out string? str))
    {
    Console.WriteLine(str);
    await Task.Delay(1000);
    }
    }
    });
    }

  • client 通过流的方式向 server 发送数据

    // 接收流
    var reader = await conn1.StreamAsChannelAsync("SendStream");
    await Task.Run(async () =>
    {
    while (await reader.WaitToReadAsync())
    {
    while (reader.TryRead(out string? str))
    {
    Console.WriteLine(str);
    await Task.Delay(1000);
    }
    }
    });

    // 发送流
    var channel = Channel.CreateUnbounded<string?>();
    await conn1.SendAsync("ReceiveClientMsgByStream", channel.Reader);
    await Task.Run(async () =>
    {
    var list = await File.ReadAllLinesAsync("001.txt");
    foreach (var line in list)
    {
    await channel.Writer.WriteAsync(line);
    }
    });

代码实现

  1. 新建一个类,写相关的业务逻辑,需要继承自 Microsoft.AspNetCore.SignalR.Hub

    public class Chat : Hub

  2. 添加 SignalR 服务

    builder.Services.AddSignalR();

  3. 注册路由

    app.MapHub("/chat");

Client

以 Console 示例

  1. 添加 nuget 包

    Microsoft.AspNetCore.SignalR.Client

  2. 创建 HubConnection,建立跟 Server 的连接

    HubConnection connection = new HubConnectionBuilder()
    .WithUrl("http://localhost:5253/chat")
    .Build();

  3. 可以增加一个 reconnect 事件

    connection.Closed += async (Exception? arg) =>
    {
    await Task.Delay(new Random().Next(0, 5) * 1000);
    await connection.StartAsync();
    };

  4. 添加一个监听事件,server 就是触发这个监听事件向 client 发送数据

    connection.On("CallByHub", (response) =>
    {
    Console.WriteLine("我是:" + connectName + "; 服务器端传来的:" + response);
    });

  5. 最后就是写业务代码了,client 调用 server 可以使用如下方式

    // 无返回值
    conn.SendAsync()

    // 有返回值
    conn.InvokeAsync<>()

Demo

https://gitee.com/rory-j-liu/signalr-demo-self

posted @ 2022-11-13 14:52  liujiangbo  阅读(576)  评论(0)    收藏  举报