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<string>> SendStream() { Console.WriteLine("==服务端通过流的方式向客户端发送信息=="); var channel = Channel.CreateUnbounded<string>(); 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<string> 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<string>("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); } });
代码实现
-
新建一个类,写相关的业务逻辑,需要继承自 Microsoft.AspNetCore.SignalR.Hub
public class Chat : Hub
-
添加 SignalR 服务
builder.Services.AddSignalR();
-
注册路由
app.MapHub<Chat>("/chat");
Client
以 Console 示例
-
添加 nuget 包
Microsoft.AspNetCore.SignalR.Client
-
创建 HubConnection,建立跟 Server 的连接
HubConnection connection = new HubConnectionBuilder() .WithUrl("http://localhost:5253/chat") .Build();
-
可以增加一个 reconnect 事件
connection.Closed += async (Exception? arg) => { await Task.Delay(new Random().Next(0, 5) * 1000); await connection.StartAsync(); };
-
添加一个监听事件,server 就是触发这个监听事件向 client 发送数据
connection.On<string>("CallByHub", (response) => { Console.WriteLine("我是:" + connectName + "; 服务器端传来的:" + response); });
-
最后就是写业务代码了,client 调用 server 可以使用如下方式
// 无返回值 conn.SendAsync() // 有返回值 conn.InvokeAsync<>()