Signalr

作用

使用Signalr可实现前后端互相主动给对方推送消息,不再是前端请求后端响应的单向模式。
Signalr会根据实际情况自动选择以下方式实现:WebSockets、Server-Sent Events、Long Polling。

代码GitHub地址:SomeExperiments

后端实现

(注:这用到了我自己写的一个nuget包【tdb.framework.webapi Version=“6.0.1.1” 】,但在这个版本还没把SignalR封装进去)

  • 修改Startup.cs
    以下代码主要关注注释中带有SignalR的代码
 public void ConfigureServices(IServiceCollection services)
   {
       //日志
       services.AddTdbNLogger();
       //设置允许所有来源跨域
       services.AddTdbAllAllowCors();
       //添加身份认证与验权服务
       services.AddAuthentication(x =>
       {
           x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
           x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
       })
       .AddJwtBearer(o =>
       {
           o.TokenValidationParameters = new TokenValidationParameters
           {
               NameClaimType = tdb.framework.webapi.standard.Auth.TdbClaimTypes.Name,
               RoleClaimType = tdb.framework.webapi.standard.Auth.TdbClaimTypes.Role,
               IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("tangdabin20220108")),
               //不验Audience
               ValidateAudience = false,
               //不验Issuer
               ValidateIssuer = false,
               //允许的服务器时间偏移量
               ClockSkew = TimeSpan.FromSeconds(10),
           };
           o.Events = new JwtBearerEvents()
           {
               OnMessageReceived = (context) =>
               {
                   if (!context.HttpContext.Request.Path.HasValue)
                   {
                       return Task.CompletedTask;
                   }

                   //这里是用来给Signalr验证身份信息用的
                   var accessToken = context.HttpContext.Request.Query["access_token"];
                   var path = context.HttpContext.Request.Path;
                   if (!(string.IsNullOrWhiteSpace(accessToken)) && path.StartsWithSegments("/AuthHub"))
                   {
                       context.Token = accessToken;
                       return Task.CompletedTask;
                   }
                   return Task.CompletedTask;
               }
           };
       });

       //授权
       services.AddAuthorization();
       //添加api版本控制及浏览服务
       services.AddTdbApiVersionExplorer();
       //swagger
       services.AddTdbSwaggerGenApiVer(o =>
       {
           o.ServiceCode = "tdb.signalR.demo";
           o.ServiceName = "SignalR Demo";
           o.LstXmlCommentsFileName.Add("SignalRService.xml");
       });

       //SignalR
       services.AddSignalR();

       //services.AddControllers();
       services.AddControllers(option =>
       {
           //异常处理
           option.AddTdbGlobalException();
       });
   }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    //设置允许所有来源跨域
    app.UseTdbAllAllowCors();
    //认证
    app.UseAuthentication();
    //授权
    app.UseAuthorization();
    //swagger
    app.UseTdbSwaggerAndUIApiVer(provider);

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();

        //前端连接Signalr的路由地址
        endpoints.MapHub<ServerTimeHub>("/ServerTimeHub");
        endpoints.MapHub<SendMsgHub>("/SendMsgHub");
        endpoints.MapHub<AuthHub>("/AuthHub");
    });

    //SignalR广播服务器时间
    BroadcastTime(app);
}
//SignalR广播服务器时间
private void BroadcastTime(IApplicationBuilder app)
 {
     Task.Factory.StartNew(async () =>
     {
         while (true)
         {
             var hubContext = app.ApplicationServices.GetService<IHubContext<ServerTimeHub, IServerTimeHub>>();
             await hubContext.Clients.All.BroadcastTime(DateTime.Now);
             await Task.Delay(1000);
         }
     });
 }
  • 继承Hub
    继承Hub写自己的业务处理(一个Hub一个链接)
    具体看已上传到github上的代码。
前端实现(VUE)
  • 安装依赖
npm install @microsoft/signalr
  • 引用对象
const signalR = require("@microsoft/signalr");
  • 链接
    不带token
   this.connMsg = new signalR.HubConnectionBuilder()
       .withUrl("http://localhost:36921/SendMsgHub", { })
	   .configureLogging(signalR.LogLevel.Information)
       .build();

带token

this.connAuth = new signalR.HubConnectionBuilder()
    .withUrl("http://localhost:36921/AuthHub", { accessTokenFactory: () => this.authToken })
    .configureLogging(signalR.LogLevel.Trace)
    .build();
  • 监听后端事件
this.connAuth.on("ReceiveMessage", data => {
	console.log("ReceiveMessage"+data);
});
  • 向后端发送消息
this.connMsg.invoke("SendToAll", this.text);
  • 生命周期
 this.connection.onreconnecting(error => {
	console.log("onreconnecting:"+error);
 });
 this.connection.onreconnected(connectionId => {
	   console.log("onreconnected:"+connectionId);
 });
 this.connection.onclose(error => {
   	console.log("onclose:"+error);
 });

具体看已上传到github上的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值