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

相关推荐
盛派网络小助手1 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
∝请叫*我简单先生2 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
zquwei3 小时前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
dessler3 小时前
Docker-run命令详细讲解
linux·运维·后端·docker
Q_19284999064 小时前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
ZSYP-S4 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
Yuan_o_5 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
程序员一诺5 小时前
【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
后端·python
DT辰白6 小时前
如何解决基于 Redis 的网关鉴权导致的 RESTful API 拦截问题?
后端·微服务·架构