万金流
以码会友。 吾Q:578751655。 水平有限,轻喷,谢!
随笔 - 189,  文章 - 0,  评论 - 7,  阅读 - 14万

写在前面:

看官网介绍,听开发者朋友的感受,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();
复制代码

结果略。

 

(完)

posted on   万金流  阅读(601)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2019-12-16 二维数组例题习题
2019-12-16 扩展方法
2019-12-16 特性的一般用法与MVC鉴权

点击右上角即可分享
微信分享提示