写在前面:
看官网介绍,听开发者朋友的感受,SignalR对websocket等多个长连接协议进行了封装,提供了多种方法,能够适应很多场合和复杂情况。单纯论简单的web长连接,它确实没有js/nodejs版的websocket直观、简单。微软的风格,一来就高大上,不知道又会劝退多少人,会不会把自己玩死。
我帮你简单入门,希望你能体会到它的美。
web端
html:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>SignalR Example</title> 5 <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script> 6 </head> 7 <body> 8 <h1>SignalR Example</h1> 9 10 <script> 11 // 创建 SignalR 连接 12 var connection = new signalR.HubConnectionBuilder() 13 .withUrl("http://localhost:5267/chathub") 14 .build(); 15 16 // 注册事件处理程序 17 connection.on("messageReceived", function (message) { 18 console.log(message); 19 }); 20 21 // 启动连接 22 connection.start() 23 .then(function () { 24 console.log("SignalR connection started."); 25 }) 26 .catch(function (err) { 27 console.error(err.toString()); 28 }); 29 30 // 发送消息 31 function sendMessage() { 32 var message = document.getElementById("messageInput").value; 33 connection.invoke("sendMessage", message) 34 .catch(function (err) { 35 console.error(err.toString()); 36 }); 37 } 38 </script> 39 40 <input type="text" id="messageInput" /> 41 <button onclick="sendMessage()">Send Message</button> 42 </body> 43 </html>
说明:
1、第5行引用官方SignalR的js库。官方位置(版本升级,链接可能会变。这里给官方文档位置图)
2、17行的事件是给服务端回调用的。
3、33行调用服务器方法,发送数据。
服务端:
新建的是asp.net的空项目,一点点添加内容。
思想:
1、SignalR的类,继承自Hub。
2、在管道里配置它,书写路径映射即可。
3、默认禁止跨域(这一点和websocket不同),前后端分离调试需要注意。
代码(路径略):
ChatHub.cs:
1 using Microsoft.AspNetCore.SignalR; 2 3 namespace SignalRChat.Hubs 4 { 5 public class ChatHub : Hub 6 { 7 public async Task SendMessage(string message) 8 { 9 await Clients.All.SendAsync("messageReceived", "server:"+message); 10 } 11 } 12 }
第7行的方法名称,通常由客户端调用。(见前面html的第33行)
第9行向客户端发送事件和参数。(对应html的第17行)
Program.cs:
1 using SignalRChat.Hubs; 2 3 namespace WebApplication1 4 { 5 public class Program 6 { 7 public static void Main(string[] args) 8 { 9 var builder = WebApplication.CreateBuilder(args); 10 11 builder.Services.AddSignalR(); 12 13 builder.Services.AddCors(options => 14 { 15 options.AddDefaultPolicy( 16 builder => 17 { 18 builder.WithOrigins("http://127.0.0.1:5500") 19 .AllowAnyHeader() 20 .WithMethods("GET", "POST") 21 .AllowCredentials(); 22 }); 23 }); 24 25 var app = builder.Build(); 26 27 app.UseCors(); 28 29 app.MapHub<ChatHub>("/chatHub"); 30 31 app.MapGet("/", () => "Hello World!"); 32 33 app.Run(); 34 } 35 } 36 }
说明:11-23、27-29行为添加。
至此,可以运行。
扩展:
index.html:
<!DOCTYPE html> <html> <head> <title>SignalR Example</title> <script src="js/signalr/signalr.js"></script> <script src="js/j1.js"></script> </head> <body> <h1>SignalR Example</h1> <input type="text" id="UserId" /> <input type="text" id="messageInput" /> <button onclick="myConn()">Connect Server</button> <button onclick="sendMessage()">Send Message</button> </body> </html>
j1.js
1 var connection; 2 function myInit(myu) { 3 // 创建 SignalR 连接 4 connection = new signalR.HubConnectionBuilder() 5 //业务逻辑:用户名(签名)等信息可以写在查询字符串里 6 .withUrl("http://localhost:5063/chathub?u="+myu) 7 .build(); 8 9 // 注册“收到消息”事件处理程序 10 connection.on("messageReceived", function (user,message) { 11 console.log(`${user} said:${message}`); 12 }); 13 14 // 注册“连接停止”事件处理程序 15 connection.on("connectStop", function (message) { 16 connection.stop(); 17 console.log(message); 18 }); 19 } 20 // 启动连接 21 function myConn() { 22 var uid = document.querySelector("#UserId").value; 23 myInit(uid); 24 connection.start() 25 .then(function () { 26 console.log("SignalR connection started."); 27 }) 28 .catch(function (err) { 29 console.error(err.toString()); 30 }); 31 32 } 33 34 // 发送消息 35 function sendMessage() { 36 var uid = document.querySelector("#UserId").value; 37 var message = document.querySelector("#messageInput").value; 38 //业务逻辑:发送“userid”,供服务端操作 39 connection.invoke("sendMessage",uid, message) 40 .catch(function (err) { 41 console.error(err.toString()); 42 }); 43 }
ChatHub.cs
using Microsoft.AspNetCore.SignalR; namespace WebApplication1.Hubs { public class ChatHub : Hub { public async Task SendMessage(string uid, string message) { //业务逻辑:根据uid,可查找用户 if (message != "over") { //发送消息给指定用户 await Clients.User(uid).SendAsync("messageReceived", uid, message); } else { //通过调用客户端断开方法,t人。 await Clients.User(uid).SendAsync("connectStop",message); } //向所有人发送消息 //await Clients.All.SendAsync("messageReceived", cid, message); } public override async Task OnConnectedAsync() { //建立连接时获取用户和系统信息 //var s1=Context.ConnectionId; //此处的用户标识由“MyUserProvider.cs”提供 var s1 = Context.UserIdentifier; //调试 Console.WriteLine($"user:{s1}"); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception? exception) { //断开连接时,可获取的信息。 Console.WriteLine($"OnDisconnectedAsync,uid={Context.UserIdentifier} connectionId={Context.ConnectionId}"); await base.OnDisconnectedAsync(exception); } } }
MyUserProvider.cs用于提供用户id的由来,需要继承IUserIdProvider接口,并在主程序单例注册
代码如下:
using Microsoft.AspNetCore.SignalR; using System.Security.Claims; namespace WebApplication1 { public class MyUserProvider : IUserIdProvider { public virtual string GetUserId(HubConnectionContext connection) { var r= connection.GetHttpContext()?.Request.Query["u"].ToString()??connection.ConnectionId; return r; } } }
主程序:
var builder = WebApplication.CreateBuilder(args); //空项目添加1 builder.Services.AddSingleton<IUserIdProvider, MyUserProvider>(); builder.Services.AddSignalR(); var app = builder.Build(); //添加2 app.UseStaticFiles(); app.MapHub<ChatHub>("/ChatHub"); app.Run();
结果略。
(完)
分类:
备忘
标签:
Blazor&WebApi
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2019-12-16 二维数组例题习题
2019-12-16 扩展方法
2019-12-16 特性的一般用法与MVC鉴权