雪花

一、在 ASP.NET Core 中使用 SignalR

一、介绍

SignalR 是一个用于实现实时网站的 Microsoft .NET 库。它使用多种技术来实现服务器与客户端间的双向通信,服务器可以随时将消息推送到连接的客户端。

https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?tabs=visual-studio&view=aspnetcore-3.0

 

 

二、新建Core MVC项目并安装

三、添加 SignalR 客户端库

在“解决方案资源管理器” 中,右键单击项目,然后选择“添加” >“客户端库” 

在“添加客户端库” 对话框中,对于“提供程序” ,选择“unpkg” 。

对于“库” ,输入 @aspnet/signalr@1,然后选择不是预览版的最新版本。

选择“选择特定文件” ,展开“dist/browser” 文件夹,然后选择“signalr.js” 和“signalr.min.js” 。

将“目标位置” 设置为 wwwroot/lib/signalr/ ,然后选择“安装” 。

 

 

 

 四、创建 SignalR 中心即操作中心。

Hub 消息处理中心

public class TestHub : Hub
{
    public TestHub()
    {
    }

    public async Task SendMessage(string message, string name)
    {
        #region Client
        //this.Context.ConnectionId                 //每个连接一个connectionId  表示唯一客户端
        //this.Clients.Client().SendAsync();        //指定发送消息
        //this.Clients.Clients()        
        #endregion             //给多个client发消息


        #region Group
        //this.Clients.Group();                     //给某个组发消息
        //this.Clients.Groups()                     //给多个组发消息
        //this.Groups.AddToGroupAsync()             //将指定连接加入组
        //this.Groups.RemoveFromGroupAsync()        //将指定连接移除组 
        #endregion

        await Clients.All.SendAsync("onMsg", DateTime.Now, message);
    }


    //上下线消息  连接、断开事件

    //客户端连接上
    public override Task OnConnectedAsync()
    {
        return base.OnConnectedAsync();
    }

    //客户端断开
    public override Task OnDisconnectedAsync(Exception exception)
    {
        string connectionId = this.Context.ConnectionId;
        return base.OnDisconnectedAsync(exception);
    }
}

以上可以看到SignalR封装了很多常用方法(发送指定消息、群发...),我们可以很简单的使用达到目的

创建 Hubs 文件夹 。

在 Hubs 文件夹中,使用以下代码创建 ChatHub.cs 文件 :

 

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Ban.Hubs
{
    public class ChatHub:Hub 
    {
        /// <summary>
        /// /服务端方法 发送消息--发送给所有连接的客户端
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessage(string user,string message)
        {
            //ReceiveMessage 为客户端方法,让所有客户端调用这个方法
            await Clients.All.SendAsync("ReceiveMessage",user,message);
        }

        /// <summary>
        /// 客户端连接的时候调用
        /// </summary>
        /// <returns></returns>
        public override Task OnConnectedAsync()
        {
            Trace.WriteLine("客户端连接成功");
            return base.OnConnectedAsync();
        }//所有链接的客户端都会在这里

        /// <summary>
        /// 连接终止时调用。
        /// </summary>
        /// <returns></returns>
        public override Task OnDisconnectedAsync(Exception exception)
        {
            Trace.WriteLine("连接终止");
            return base.OnDisconnectedAsync(exception);
        }
       
    }
}

六、配置 SignalR

必须配置 SignalR 服务器,以将 SignalR 请求传递到 SignalR。

startupConfigureServices方法内部添加SignalR服务services.AddSignalR();Configure中配置具体的Hub(路由器、中转):

    app.UseSignalR(routes =>
    {
        routes.MapHub<TestHub>("/testHub");     //可以多个map
    });
    
    app.UseMvc();           //注意UseSignalR需要在UseMvc()之前

这样SignalR服务器端就开发完成了,网页、Java、.Net客户端都可以连接的

 

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using test.Hubs; //3、引用 处理客户端 - 服务器通信的高级管道
namespace test
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddSignalR();//1、添加服务
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSignalR(routes => //2、引用
            {
                routes.MapHub<ChatHub>("/chatHub");
            });
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

 

 七、添加 SignalR 客户端代码(创建index控制器和视图)

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div class="container">
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-6">&nbsp;</div>
            <div class="col-6">
                User..........<input type="text" id="userInput" />
                <br />
                Message...<input type="text" id="messageInput" />
                <input type="button" id="sendButton" value="Send Message" />
            </div>
        </div>
        <div class="row">
            <div class="col-12">
                <hr />
            </div>
        </div>
        <div class="row">
            <div class="col-6">&nbsp;</div>
            <div class="col-6">
                <ul id="messagesList"></ul>
            </div>
        </div>
    </div>
    <script src="~/lib/signalr/dist/browser/signalr.js"></script>
    <script type="text/javascript">
        "use strict";
        var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
        //在建立连接之前禁用发送按钮
        document.getElementById("sendButton").disabled = true;
        //接受消息
        connection.on("ReceiveMessage", function (user, message) {
            var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
            var encodedMsg = user + " says " + msg;
            var li = document.createElement("li");
            li.textContent = encodedMsg;
            document.getElementById("messagesList").appendChild(li);
        });
        //开始链接
        connection.start().then(function () {
            document.getElementById("sendButton").disabled = false;
        }).catch(function (err) {
            return console.error(err.toString());
        });
        //发送消息
        document.getElementById("sendButton").addEventListener("click", function (event) {
            var user = document.getElementById("userInput").value;
            var message = document.getElementById("messageInput").value;
            connection.invoke("SendMessage", user, message).catch(function (err) {
                return console.error(err.toString());
            });
            event.preventDefault();
        });
    </script>
</body>
</html>

 

 

 

 

 

 

Controller中调用SignalR服务

在构造函数注入IHubContext<>就可以直接使用了,非常方便:

   private readonly IHubContext<TestHub> _hubContext;

    public HomeController(IHubContext<TestHub> hubContext)
    {
        _hubContext = hubContext;
    }
    
    public async Task<IActionResult> Notify()
    {
        //拿不到当前Hub的clientId  线程是唯一的
        await _hubContext.Clients.All.SendAsync("onMsg", "from controller msg");
        return Ok();
    }

 

 

 

 

posted @ 2019-09-24 10:09  十色  阅读(4084)  评论(1编辑  收藏  举报