ASP.NET Core 使用 SignalR 实现实时通讯

🐳简介

SignalR是一个用于ASP.NET的库,它允许服务器代码向连接的客户端实时发送推送通知。它使用WebSockets作为底层传输机制,但如果浏览器不支持WebSockets,它会自动回退到其他兼容的技术,如服务器发送事件(Server-Sent Events)或长轮询。

SignalR的主要特点是它支持双向通信,这意味着服务器可以主动向客户端发送消息,而客户端也可以发送消息给服务器。这与传统的HTTP请求不同,后者通常是单向的,即客户端向服务器发送请求,然后等待响应。

SignalR的使用场景包括:

  1. 聊天应用:SignalR可以用来构建实时聊天应用,用户可以即时接收和发送消息。

  2. 实时数据更新:例如股票交易平台,可以使用SignalR实时更新股票价格和交易信息。

  3. 协作工具:多用户编辑同一文档或共享白板时,可以使用SignalR来同步不同用户的操作。

  4. 游戏:多人在线游戏可以使用SignalR来同步玩家的动作和游戏状态。

  5. 实时通知:网站可以使用SignalR来推送通知给用户,例如新消息提醒或系统更新通知。

  6. 物联网(IoT):可以使用SignalR来实时监控和控制连接的设备。

🐳案例演示

首先,创建一个asp.net core web api

👻定义通讯中心类

定义一个名为 ChatHub 的 SignalR 通讯中心类,继承 Hub 类。

  1. SendMsg 方法:这是一个自定义方法,它可以被前端客户端通过 SignalR 连接调用,当客户端调用此方法时,它会接收一个用户ID (userId) 和一条消息 (msg),然后将格式化后的消息发送给连接的客户端。如下代码,使用All则是发送给所有客户端,使用Others则是发送给除自己以外的所有客户端。

  2. OnConnectedAsync 方法:重写方法,当客户端成功连接到 ChatHub 时,会触发此方法。在这个示例中,方法体为空,但可以在这里添加连接时需要执行的逻辑。

  3. OnDisconnectedAsync 方法:重写方法,当客户端断开与 ChatHub 的连接时,会触发此方法。同样,方法体为空,但可以在这里添加断开连接时需要执行的逻辑。

cs 复制代码
public class ChatHub : Hub
{
    public async Task SendMsg(long userId, string msg)
    {
        string sendMsg = $"服务的收到你的消息,user={userId},msg={msg}";
        //服务端推送给所有客户端
        await Clients.All.SendAsync("ReceiveMsg", sendMsg); 
        //服务端推送给 除自已以外 的所有客户端
        await Clients.Others.SendAsync("ReceiveMsg", sendMsg);
    }

    //客户端成功连接时,会触发此方法
    public override Task OnConnectedAsync()
    {
        return Task.CompletedTask;
    }

    //客户端断开连接时,会触发此方法
    public override Task OnDisconnectedAsync(Exception? exception)
    {
        return Task.CompletedTask;
    }
}

👻添加SignalR服务与配置跨域

打开Program,如下代码中四处注释处添加代码

cs 复制代码
using SignalRServer.Hubs;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//添加SignalR服务
builder.Services.AddSignalR();
//配置跨域
builder.Services.AddCors(opt =>
{
    opt.AddPolicy("WS.Client", p =>
    {
        p.AllowCredentials();
        p.AllowAnyHeader();
        p.AllowAnyMethod();
        p.SetIsOriginAllowed(s => true); //允许任何客户
        //指定跨域
        // p.WithHeaders();
    });
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
//在处理管道中启用策略
app.UseCors("WS.Client");
app.UseAuthorization();

app.MapControllers();
//映射通讯中心的请求路径
app.MapHub<ChatHub>("/Hubs");
app.Run();

然后就可以启动我们的项目了!

👻客户端

写两个html来测试一下

html 复制代码
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>通讯1</title>
</head>
<body>
<input type="button" value="发送" id="btnSend">
</body>
</html>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/@microsoft/signalr/dist/browser/signalr.min.js"></script>

<script>
  var connection = new signalR.HubConnectionBuilder()
  .withUrl("http://localhost:5039/Hubs")
  .build();
  //当连接成功的时候
  connection.start().then(function (){
    console.log("客户端连接成功")
  })
  
  //接受服务端主动推送过来的消息
  connection.on("ReceiveMsg",function(msg){
    alert(msg);
  })
  $('#btnSend').click(function(){
    connection.invoke("SendMsg",1,"测试1").catch(function(err){
      console.log(err);
    });
  })

</script>

第二个html只用在connection.invoke()时把参数换一下就好了,打开两个HTML,控制台看一下输出,连接成功

通讯1的网页中点一下发送,再切换到通讯2网页,收到了服务器发来的消息

🐤此案例已上传到gitee中,案例地址👇

SignalR案例 (gitee.com)https://gitee.com/libihao520/signalR-case-study

相关推荐
ღ᭄ꦿ࿐Never say never꧂4 分钟前
微服务架构中的负载均衡与服务注册中心(Nacos)
java·spring boot·后端·spring cloud·微服务·架构·负载均衡
.生产的驴13 分钟前
SpringBoot 消息队列RabbitMQ 消息确认机制确保消息发送成功和失败 生产者确认
java·javascript·spring boot·后端·rabbitmq·负载均衡·java-rabbitmq
海里真的有鱼21 分钟前
Spring Boot 中整合 Kafka
后端
布瑞泽的童话27 分钟前
无需切换平台?TuneFree如何搜罗所有你爱的音乐
前端·vue.js·后端·开源
写bug写bug37 分钟前
6 种服务限流的实现方式
java·后端·微服务
离开地球表面_991 小时前
索引失效?查询结果不正确?原来都是隐式转换惹的祸
数据库·后端·mysql
Victor3561 小时前
Oracle(138)如何监控数据库性能?
后端
不修×蝙蝠2 小时前
eclipse使用 笔记02
前端·笔记·后端·eclipse
吃面不喝汤664 小时前
Flask + Swagger 完整指南:从安装到配置和注释
后端·python·flask
讓丄帝愛伱5 小时前
spring boot启动报错:so that it conforms to the canonical names requirements
java·spring boot·后端