当前位置: 首页 > news >正文

SignalR 底层原理详解

1. 整体架构概览

客户端 (JavaScript) ←→ 传输层 ←→ SignalR Hub ←→ 业务逻辑↓                    ↓              ↓WebSocket           HTTP/WebSocket   C# 方法长轮询               JSON 序列化      RPC 调用Server-Sent Events  二进制协议

2. 传输层协议

2.1 WebSocket (首选)

// 客户端建立 WebSocket 连接
const connection = new signalR.HubConnectionBuilder().withUrl("/chathub").build();// 底层实际是:
const ws = new WebSocket("ws://localhost:5000/chathub");

WebSocket 握手过程:

1. 客户端发送 HTTP Upgrade 请求GET /chathub HTTP/1.1Upgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==2. 服务器响应 101 Switching ProtocolsHTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=3. 建立双向通信通道

2.2 长轮询 (Fallback)

// 当 WebSocket 不可用时,自动降级到长轮询
// 客户端定期发送请求,服务器保持连接打开

长轮询机制:

1. 客户端发送 POST 请求到 /chathub/negotiate
2. 服务器返回连接信息
3. 客户端发送 POST 请求到 /chathub/poll
4. 服务器保持连接打开,等待消息
5. 有消息时立即返回,无消息时超时返回
6. 客户端立即发起下一个请求

3. RPC 调用机制

3.1 客户端到服务器 (Client → Server)

// JavaScript 调用
connection.invoke("SendMessage", "用户名", "消息内容");

底层实现:

// 发送的 JSON 消息
{"protocol": "json","version": 1,"type": 1,  // 1 = Invocation"target": "SendMessage","arguments": ["用户名", "消息内容"],"invocationId": "12345"
}

服务器端处理:

// SignalR 自动路由到对应方法
public class ChatHub : Hub
{public async Task SendMessage(string user, string message){// 这里就是 RPC 调用的目标方法await Clients.All.SendAsync("ReceiveMessage", user, message);}
}

3.2 服务器到客户端 (Server → Client)

// C# 服务器调用
await Clients.All.SendAsync("ReceiveMessage", user, message);

底层实现:

// 发送给客户端的 JSON 消息
{"protocol": "json","version": 1,"type": 1,  // 1 = Invocation"target": "ReceiveMessage","arguments": ["用户名", "消息内容"]
}

客户端处理:

// JavaScript 接收处理
connection.on("ReceiveMessage", (user, message) => {// 这里就是 RPC 调用的目标函数addMessage(user, message);
});

4. 消息序列化

4.1 JSON 协议 (默认)

// 服务器配置
services.AddSignalR().AddJsonProtocol(options =>{options.PayloadSerializerOptions.PropertyNamingPolicy = null;});

序列化过程:

// C# 对象
var message = new { User = "张三", Content = "你好" };// 序列化为 JSON
{"User": "张三","Content": "你好"
}// 包装为 SignalR 消息
{"protocol": "json","version": 1,"type": 1,"target": "ReceiveMessage","arguments": [{"User": "张三", "Content": "你好"}]
}

4.2 二进制协议 (高性能)

// 使用 MessagePack 序列化
services.AddSignalR().AddMessagePackProtocol();

5. 连接生命周期

5.1 连接建立

1. 客户端发起连接请求
2. 服务器创建 Hub 实例
3. 调用 OnConnectedAsync()
4. 建立传输通道
5. 开始消息交换

5.2 消息路由

客户端消息 → SignalR 路由 → Hub 方法 → 业务逻辑
业务逻辑 → Hub 方法 → SignalR 路由 → 客户端回调

5.3 连接断开

1. 检测连接断开
2. 调用 OnDisconnectedAsync()
3. 清理资源
4. 通知其他客户端

6. 分组和用户管理

6.1 分组机制

// 服务器端
await Groups.AddToGroupAsync(Context.ConnectionId, "房间1");
await Clients.Group("房间1").SendAsync("ReceiveMessage", "房间消息");

底层实现:

// 内部消息格式
{"type": 7,  // 7 = AddToGroup"groupName": "房间1"
}

6.2 用户管理

// 服务器端
await Clients.User("用户ID").SendAsync("ReceiveMessage", "私聊消息");

7. 错误处理和重连

7.1 自动重连

const connection = new signalR.HubConnectionBuilder().withUrl("/chathub").withAutomaticReconnect([0, 2000, 10000, 30000]) // 重连间隔.build();

7.2 错误处理

connection.onclose(error => {if (error) {console.log("连接错误:", error);} else {console.log("连接正常关闭");}
});

8. 性能优化

8.1 消息批处理

// 服务器端批量发送
var tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{tasks.Add(Clients.All.SendAsync("ReceiveMessage", $"消息{i}"));
}
await Task.WhenAll(tasks);

8.2 连接池管理

// 服务器端连接管理
public class ChatHub : Hub
{private static readonly ConcurrentDictionary<string, DateTime> _connections = new();public override async Task OnConnectedAsync(){_connections[Context.ConnectionId] = DateTime.UtcNow;await base.OnConnectedAsync();}
}

9. 安全机制

9.1 身份验证

[Authorize]
public class ChatHub : Hub
{public async Task SendMessage(string message){var user = Context.User.Identity.Name;await Clients.All.SendAsync("ReceiveMessage", user, message);}
}

9.2 授权策略

[Authorize(Policy = "ChatPolicy")]
public class ChatHub : Hub
{// 只有通过授权策略的用户才能访问
}

10. 调试和监控

10.1 日志记录

// 启用详细日志
services.AddSignalR().AddHubOptions<ChatHub>(options =>{options.EnableDetailedErrors = true;});

10.2 性能监控

// 连接统计
public class ConnectionStats
{public int TotalConnections { get; set; }public int ActiveConnections { get; set; }public DateTime LastActivity { get; set; }
}

总结

SignalR 的底层原理可以概括为:

  1. 传输层:WebSocket 为主,长轮询为备
  2. RPC 机制:双向方法调用,JSON 序列化
  3. 消息路由:自动路由到对应的方法/回调
  4. 连接管理:生命周期管理,自动重连
  5. 性能优化:批处理,连接池,缓存
  6. 安全机制:身份验证,授权策略

这就是为什么 JavaScript 能调用 C# 方法,C# 能调用 JavaScript 函数的根本原理!

http://www.dtcms.com/a/516571.html

相关文章:

  • 企业应该如何进行网站推广济南建设大厦
  • Java面试题-两个对象相等equals相等吗,equals相等对象相等吗
  • 网站建设汇报材料链接买卖
  • 外贸型网站该如何推广甘肃网络公司网站
  • 外国做的福利小视频在线观看网站网站建设现状调查研究
  • DevEco Studio与Web联合开发:打造鸿蒙混合应用的全景指南
  • 动力网站网站关键词优化的步骤和过程
  • Kotlin 高阶函数在回调设计中的最佳实践
  • gh-ost菜鸟教程
  • 湖南微信网站公司网页显示网站正在建设中怎么做
  • 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-27- 操作单选和多选按钮 - 上篇(详细教程)
  • 网站建设与管理培训总结网站规划有前途吗
  • 下载空excel和导出带有查询数据的excel的区别
  • 智元灵犀X1-本体通讯架构分析2:CAN/FD总线性能优化分析
  • 深圳最简单的网站建设wordpress中文名字注册
  • 软件开发的创意提案详解
  • 外贸建站 知乎深圳建设工程交易平台
  • Spring Cloud - Spring Cloud 负载均衡(Ribbon 负载均衡概述、Ribbon 使用)
  • 行业网站运营网站上可以做文字链接么
  • 通达信--报表分析
  • 做谷歌推广一定要网站吗it运维需要具备哪些能力
  • 大模型数据筛选、分类、生成任务,满足并发速度和处理准确要求
  • CentOS系统yum list使用指南
  • 社保减员要怎么做 国税局网站建设工程用地批准手续在哪个网站
  • “HTTPS 个人化”实战,个人站点与设备调试的部署、验证与抓包排查方法
  • 手机网站cms 开源中国主流媒体平台有哪些
  • 档案管理系统有什么好处?核心功能让档案管理效率提升
  • 基于MountainTop数据的STAP算法仿真实现
  • Linux驱动之USB、MIPI摄像头驱动
  • TypeScript 面试题及详细答案 100题 (71-80)-- 模块与命名空间