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服务端调用客户端方法说明: 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);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication3.ServerHub
{
public interface IMyService
{
Task<string> SayHello();
Task Sleep();
}
}
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);
}
}
}
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}----------");
});
}
///
/// Excute
///
///
public async Task<dynamic> RequestServer1()
{
var result = await connection.InvokeAsync<dynamic>("Excute", "WebApplication3.ServerHub.IMyService", "SayHello", new object[] { });
return result;
}
///
/// ExcuteWithoutResult
///
///
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; }
}
}
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;
}
}
}
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()前面
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("/ServerHub"));
app.UseWebSockets();
在这里服务端基本就配置好了,运行项目,页面出现Hello,服务端没有什么问题
客户端安装signalR
(1)在“解决方案资源管理器” 中,右键单击项目,然后选择“添加” >“客户端库” 。
(2)在“添加客户端库” 对话框中,对于“提供程序” ,选择“unpkg” 。
(3)对于“库” ,输入 @microsoft/signalr@3,然后选择不是预览版的最新版本
(4)选择“选择特定文件” ,展开“dist/browser” 文件夹,然后选择“signalr.js” 和“signalr.min.js”
(5)将“目标位置” 设置为 wwwroot/lib/signalr/ ,然后选择“安装”
页面代码如下
@{
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>