SignalR服务端与客户端的调用案列

介绍

ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。

SignalR的可使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式。

SignalR 提供了一个用于创建服务器到客户端 《远程过程调用(RPC》的 API。 RPC 通过服务器端 .NET Core 代码调用客户端上的 JavaScript 函数。

一.创建项目、配置环境

1.创建一个asp.net core 3.1 web应用程序
2.导入NuGet包:

Microsoft.AspNetCore.SignalR
Microsoft.AspNetCore.SignalR.Client
Microsoft.AspNetCore.SignalR.Client.Core

二.创建一个SignalR中心

signalR服务端调用客户端方法说明: https://blog.csdn.net/niuc321/article/details/80348108

using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication3.ServerHub
{
    public class ServerHub : Hub
    {
        private readonly IServiceProvider _serviceProvider;
        public ServerHub(IServiceProvider serviceProvider)

        {

            _serviceProvider = serviceProvider;

        }
        public async Task<dynamic> Excute(string serverName, string functionName, object[] parameters)
        {
            return await Task.Factory.StartNew(() =>

            {

                var type = Type.GetType(serverName);

                var service = _serviceProvider.GetRequiredService(type);

                var method = type.GetMethod(functionName);

                var resultTask = method.Invoke(service, new object[] { }) as Task;

                dynamic result = resultTask.GetType().GetProperty("Result").GetValue(resultTask, null);

                return result;

            });

        }


        public async Task ExcuteWithoutResult(string serverName, string functionName, object[] parameters)
        {

            var type = Type.GetType(serverName);

            var service = _serviceProvider.GetRequiredService(type);

            var method = type.GetMethod(functionName);

            var resultTask = method.Invoke(service, new object[] { }) as Task;

            await resultTask;

            var msg = JsonConvert.SerializeObject(parameters);//task done

            await Clients.Caller.SendAsync("callback", msg);

        }

        //发送消息--发送给所有连接的客户端
        public Task SendMessage(string msg)
        {
            return Clients.All.SendAsync("ReceiveMessage", msg);
        }
    }
}

三.服务端进行推送

  1. 创建IMyService接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication3.ServerHub
{
    public interface IMyService
    {
        Task<string> SayHello();

        Task Sleep();
    }
}

  1. 创建MyService类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication3.ServerHub
{
    public class MyService : IMyService
    {
        public async Task<string> SayHello()
        {
            return await Task.Factory.StartNew(() => "Hello");
        }

        public async Task Sleep()
        {
            await Task.Delay(3000);
        }
    }
}

  1. 创建SignalRClient类
using Microsoft.AspNetCore.SignalR.Client;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication3.ServerHub
{
    public class SignalRClient
    {
        private readonly HubConnection connection;
        //
        public SignalRClient()
        {

            connection = new HubConnectionBuilder()

                .WithUrl("https://localhost:44365/ServerHub")

                //.AddMessagePackProtocol()

                .Build();



            connection.Closed += async (error) =>

            {

                await Task.Delay(new Random().Next(0, 5) * 1000);

                await connection.StartAsync();

            };

            InitOnMethod();

            connection.StartAsync().ConfigureAwait(false).GetAwaiter().GetResult();

        }

        private void InitOnMethod()

        {

            connection.On<string>("callback", (msg) =>
            {

                Console.WriteLine($"------------{msg}----------");

            });

        }
        /// <summary>
        /// Excute
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> RequestServer1()
        {
            var result = await connection.InvokeAsync<dynamic>("Excute", "WebApplication3.ServerHub.IMyService", "SayHello", new object[] { });
            return result;
        }
        /// <summary>
        /// ExcuteWithoutResult
        /// </summary>
        /// <returns></returns>
        public async Task RequestWithoutResult()
        {

            await connection.SendAsync("ExcuteWithoutResult", "WebApplication3.ServerHub.IMyService", "Sleep", new object[] { });

        }

        public async Task<dynamic> RequestSendMessage()
        {

            var result = await connection.InvokeAsync<dynamic>("SendMessage", JsonConvert.SerializeObject(new ContentMessage() { name="admin",message="后端消息"}));
            return result;
        }

    }
    public class ContentMessage
    {
        public string name { get; set; }
        public string message { get; set; }
    }
}

  1. 在home控制器中输入
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using WebApplication3.Models;
using WebApplication3.ServerHub;

namespace WebApplication3.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly SignalRClient _signalRClient;
        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
            _signalRClient = new SignalRClient();
        }

        // GET home/Get
        [HttpGet]
        public async Task<ActionResult<dynamic>> Get()
        {

            var str = await _signalRClient.RequestServer1().ConfigureAwait(false);

            await _signalRClient.RequestWithoutResult().ConfigureAwait(false);

            
            return str;

        }
        
		// GET home/GetMasgerss
        [HttpGet]
        public async Task<ActionResult<dynamic>> GetMasgerss()
        {

            var str = await _signalRClient.RequestSendMessage().ConfigureAwait(false);

            return str;

        }
    }
}

四.如何在Startup配置中配置SignalR

  1. 在ConfigureServices中加入
			services.AddScoped<IMyService, MyService>();//依赖注入
            services.AddSingleton<SignalRClient>();
			//SignalR跨域配置
            services.AddCors(options =>
            {
                options.AddPolicy("any", builder =>
                {
                    builder.SetIsOriginAllowed(origin => true)
                    .WithOrigins("http://localhost:44365")
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials();
                });
                //公开使用
                options.AddPolicy("all", builder =>
                {
                    builder.WithOrigins("*")
                    .AllowAnyMethod()
                    .AllowAnyHeader();
                });
            });
            services.AddSignalR();//要写在addmvc()前面
  1. 在Configure中加入
			app.UseRouting();
            app.UseAuthorization();

            //跨域配置
            app.UseCors("any");

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Get}/{id?}");
                //配置 SignalR 服务器
                endpoints.MapControllers();
                endpoints.MapHub<WebApplication3.ServerHub.ServerHub>("/ServerHub");
            });

            //方式处注册不支持跨域
            //app.UseSignalR(routes => routes.MapHub<WebApplication3.ServerHub.ServerHub>("/ServerHub"));

            app.UseWebSockets();

在这里服务端基本就配置好了,运行项目,页面出现Hello,服务端没有什么问题

五.客户端

  1. 客户端安装signalR
    (1)在“解决方案资源管理器” 中,右键单击项目,然后选择“添加” >“客户端库” 。
    (2)在“添加客户端库” 对话框中,对于“提供程序” ,选择“unpkg” 。
    (3)对于“库” ,输入 @microsoft/signalr@3,然后选择不是预览版的最新版本
    (4)选择“选择特定文件” ,展开“dist/browser” 文件夹,然后选择“signalr.js” 和“signalr.min.js”
    (5)将“目标位置” 设置为 wwwroot/lib/signalr/ ,然后选择“安装”

  2. 页面代码如下

@{
    ViewData["Title"] = "Home Page";
}
<div>
    <ul class="form-group" id="messagesListUl" style="margin-bottom:20px"></ul>

    <form>
        <div class="form-group">
            <label for="username">姓名:</label>
            <input type="text" class="form-control" id="username" name="username">
        </div>
        <div class="form-group">
            <label for="msgcontent">内容:</label>
            <textarea rows="5" cols="20" id="msgcontent" name="msgcontent" class="form-control"></textarea>
        </div>
        <input type="button" onclick="btnSendMsg()" value="发送">
        <input type="button" onclick="btnSendMsg1()" value="后端发送">
    </form>
</div>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/signalr/dist/browser/signalr.js"></script>
<script type="text/javascript">
    //创建连接对象connection
    const signalr_connection = new signalR.HubConnectionBuilder()
        .withUrl("https://localhost:44365/ServerHub")
        .configureLogging(signalR.LogLevel.Information)
        .build();

    //启动connection
    signalr_connection.start()
        .then(function () {
            console.log("连接成功");
        }).catch(function (ex) {
            console.log("连接失败" + ex);
            //SignalR JavaScript 客户端不会自动重新连接,必须编写代码将手动重新连接你的客户端
            setTimeout(() => start(), 5000);
        });

    async function start() {
        try {
            await signalr_connection.start();
            console.log("connected");
        } catch (err) {
            console.log(err);
            setTimeout(() => start(), 5000);
        }
    };

    signalr_connection.onclose(async () => {
        start();
    });


    //绑定事件("ReceiveMessage"和服务器端的SendMessage方法中的第一个参数一致)
    signalr_connection.on("ReceiveMessage", function (data) {
        var msgObj = JSON.parse(data);//json串转对象
        const li = document.createElement("li");
        li.textContent = msgObj.name + " : " + msgObj.message;
        document.getElementById("messagesListUl").appendChild(li);
    });

    //发送消息
    function btnSendMsg() {
        var username = $.trim($("#username").val());
        var msgcontent = $.trim($("#msgcontent").val());
        var msgObj = {};
        msgObj.name = username;
        msgObj.message = msgcontent;

        var jsonmessage = {};
        jsonmessage.serverName = "WebApplication3.ServerHub.ServerHub";
        jsonmessage.functionName = "ExcuteWithoutResult";
        jsonmessage.parameters = msgObj;

        var jsonstr = JSON.stringify(msgObj);//对象转json串
        console.log(jsonstr);

        signalr_connection.invoke("SendMessage", jsonstr).catch(err => console.error("发送失败:" + err.toString()));

        //signalr_connection.invoke('getAllStocks').done(function (stocks) {
        //    $.each(stocks, function () {
        //        var stock = this;
        //        console.log("Symbol=" + stock.Symbol + " Price=" + stock.Price);
        //    });
        //}).fail(function (error) {
        //    console.log('Error: ' + error);
        //});
    }

    //发送消息
    function btnSendMsg1() {
        $.get("https://localhost:44365/Home/GetMasgerss", function (result) {
            
        });
    }
</script>

效果展示

在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐