WSHub.FreeRedis 0.0.2

dotnet add package WSHub.FreeRedis --version 0.0.2
                    
NuGet\Install-Package WSHub.FreeRedis -Version 0.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WSHub.FreeRedis" Version="0.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WSHub.FreeRedis" Version="0.0.2" />
                    
Directory.Packages.props
<PackageReference Include="WSHub.FreeRedis" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WSHub.FreeRedis --version 0.0.2
                    
#r "nuget: WSHub.FreeRedis, 0.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WSHub.FreeRedis@0.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WSHub.FreeRedis&version=0.0.2
                    
Install as a Cake Addin
#tool nuget:?package=WSHub.FreeRedis&version=0.0.2
                    
Install as a Cake Tool

WSHub

基于 .NET 的现代 WebSocket 即时通讯服务框架,参考并改进自 FreeIM。

职责清晰、可扩展、支持多节点部署,适用于游戏、IM、实时协作等场景。

.NET Version Tests License

特性

  • 发送与投递分离 — IMessageHandler(发送) + IMessageDeliveryHandler(投递)独立管道
  • 多节点支持 — 水平扩展,通过 Redis(FreeRedis)或 InMemory 进行消息路由
  • 后端语义一致 — InMemory 与 FreeRedis 共用同一套 ChannelBus 键、引用计数订阅/退订与本地投递语义,并由 RoomDemoFreeRedisE2ETests 在真实 Redis 上交叉验收
  • 多租户隔离 — 租户段由 Hub 强制注入总线键({prefix}:ch:{tenantId}:{channelId}),业务层无法绕过
  • 二进制消息 — byte[] 管道 + 路由头(0xFE),支持 protobuf
  • 连接收口 — ConnectionCloser 是断连与空闲回收的唯一路径:停发送队列 → 退频道 → 注销 presence → 关 socket
  • 活跃度保活 + 回板兜底 — 接收循环/心跳刷新 connIndex TTL;进程崩溃由宿主周期任务清理
  • 事件机制 — 上线/下线/断连/频道进出事件
  • 多目标框架 — net8.0 (LTS) / net9.0 / net10.0
  • Native AOT — InMemory 模式支持 Docker AOT 部署
  • 测试规模 — 662 个测试(单元 + Testcontainers/Redis 集成 + AOT 容器,详见 CI)

快速开始

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddWSHub<long>(options =>
{
    options.KeyPrefix = "wshub_v1";
    options.Servers = new[] { "localhost:5299" };
    options.Server = "localhost:5299";
})
.AddClientIdConverter<long, LongClientIdConverter>()
.UseInMemoryStorage<long>()       // 开发环境;生产用 .UseFreeRedisStorage(redis)
.AddDefaultHandlers<long>();      // 一键注册 Handler + Dispatcher + 后台服务

var app = builder.Build();
app.UseWebSockets();

app.Map("/ws/{tenantId?}", async (string? tenantId, HttpContext context) =>
{
    var handler = context.RequestServices.GetRequiredService<WebSocketConnectionHandler<long>>();
    await handler.HandleAsync(tenantId, context);
});

app.Run();

完整示例见 samples/MinimalApiSample/。

文档

文档 用途
docs/ARCHITECTURE-MAP.md 入口。架构对照稿 + 代码导航:设想 vs 现在的差异、冻结边界、键表、核对某条结论该看哪个文件
docs/ARCHITECTURE.md 规范性架构定义:边界、约束(C1–C6)、发布目标、Redis 键布局
docs/PROTOCOL.md 调用方契约:Control API、WebSocket 帧、202 语义、反模式
docs/DEMO-GAPS.md 做 RoomDemo 时实际撞到的 Hub 能力缺口(含 path 证据),下一步选型的输入

架构概览

客户端 WebSocket ──→ ProcessClientMessage ──→ MessageHandlerDispatcher ──→ IMessageHandler (发送)
                                                                                │
应用层主动发送 ──→ IApplicationMessageService ──→ MessageHandlerDispatcher ──→ IMessageHandler (发送)
                                                                                │
                                                                        IMessagePublisher
                                                                                │
                                                                    Redis / InMemory 消息总线
                                                                                │
                                                                        IMessageListener
                                                                                │
                                                                        HandleIncomingMessage
                                                                                │
                                                                        MessageDeliveryDispatcher ──→ IMessageDeliveryHandler (投递)
                                                                                                        │
                                                                                                ConnectionManager ──→ WebSocket

项目结构

WSHub/
├── src/
│   ├── WSHub.Abstractions/       # 接口、模型、Options
│   ├── WSHub.AspNetCore/         # ASP.NET Core 集成
│   ├── WSHub.Host/              # Control HTTP API 独立宿主
│   ├── WSHub.InMemory/           # InMemory 存储后端(开发/测试)
│   └── WSHub.FreeRedis/          # FreeRedis 存储后端(生产/多节点)
├── samples/
│   ├── MinimalApiSample/         # 基础示例 + 测试页面
│   ├── ImDemo/                   # ⚠ 绕开 Hub 的连接循环,仅作玩法参考
│   ├── GameDemo/                 # Protobuf HTML5 实时游戏
│   ├── RoomDemo/                 # 房间基础能力对照 + 可切 FreeRedis 后端的交叉验收
│   ├── RoomChatDemo/             # 多房间同时订阅 + 样例侧在线列表
│   ├── OfficialImDemo/           # 私聊/群聊走正式连接路径;历史显式标注为样例能力
│   └── AotDemo/                  # Native AOT Docker 部署示例
├── benchmarks/
│   └── WSHub.Benchmarks/         # BenchmarkDotNet 性能基准
├── tests/                        # 7 个测试项目,662 测试
├── docs/                         # 架构对照稿 + 架构规范 + 协议契约 + 性能分析
└── .github/workflows/            # CI/CD (coverage + publish + DingTalk)

性能 (BenchmarkDotNet)

操作 延迟 说明
PublishAsync 140 ns 单条消息发布
PublishBatchAsync ×100 13.9 μs 批量发布
RegisterAsync 1.08 μs / 248 B 连接注册
HasOnlineAsync 2.3 ns 在线检查

详见 docs/WSHub性能优化总结-1至10.md。

Samples

项目 说明
MinimalApiSample 基础 WebSocket + Channel + Broadcast
GameDemo Protobuf HTML5 多人实时游戏(手写 JS protobuf 编解码器)
RoomDemo 房间基础能力对照:走正式连接路径,重连补偿显式标注为样例行为;Storage:Backend=FreeRedis 可切生产后端做交叉验收
RoomChatDemo 一条连接同时订阅多个房间;样例侧「在线成员」是 GetOnlineClientIdsAsync 的近似,偏差由测试显式断言
OfficialImDemo 私聊 dm:{min}:{max} / 群聊走正式连接路径;好友与群成员校验在样例(403);内存历史标注为样例能力
ImDemo ⚠ 绕开 Hub(自建连接循环),只作业务玩法参考,不能用于验证 Hub 能力
AotDemo Native AOT + Docker 部署(docker compose up -d)

运行样例

dotnet run --project samples/RoomDemo          # http://localhost:5300
dotnet run --project samples/RoomChatDemo      # http://localhost:5500
dotnet run --project samples/OfficialImDemo    # http://localhost:5400
dotnet run --project samples/ImDemo            # http://localhost:5000 ⚠ 绕开 Hub,仅作玩法参考

多目标框架的样例(net8.0;net9.0;net10.0)必须显式指定框架,否则 dotnet run 报 Your project targets multiple frameworks:

dotnet run --project samples/GameDemo --framework net10.0           # http://localhost:5200
dotnet run --project samples/MinimalApiSample --framework net10.0   # http://localhost:5299

端口来自各自的 Properties/launchSettings.json,必须与 Program.cs 里的 options.Server / options.Servers 一致 —— 连接端点返回的 ws:// 地址就是按它拼的。

每个样例页面顶部都写了操作顺序(先连接,再进房/进会话,才收得到消息)。 只连上但没进房时,发送仍然返回 200,但 Hub 无从投递给你自己。

运行测试

dotnet test tests/WSHub.Abstractions.Tests/
dotnet test tests/WSHub.AspNetCore.Tests/
dotnet test tests/WSHub.InMemory.Tests/
dotnet test tests/WSHub.FreeRedis.Tests/
dotnet test tests/WSHub.IntegrationTests/
dotnet test tests/WSHub.Samples.Tests/      # 样例端到端(含 RoomDemo 的 FreeRedis 交叉验收)
dotnet test tests/WSHub.AotTests/           # 需要 Docker:构建 AOT 镜像并起容器

WSHub.Samples.Tests 里的 RoomDemoFreeRedisE2ETests 会起一个 redis:7-alpine Testcontainer, 用真实 Redis 把 RoomDemo 的「成员收到、非成员收不到」重跑一遍 —— 样例代码不变,只切 Storage:Backend。测试机上已有 Redis 时可设 REDIS_CONNECTION_STRING 复用,跳过启动容器。

运行 Benchmark

dotnet run -c Release --project benchmarks/WSHub.Benchmarks/

CI/CD

Workflow 触发 说明
coverage.yml push / PR 覆盖率报告 (dotnet-coverage)
publish-nuget.yml release / manual NuGet 发布 + 钉钉通知

贡献

欢迎提交 Issue 和 Pull Request。

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.2 77 10/1/2026
0.0.1 73 10/1/2026
0.0.0.41 148 8/11/2026
0.0.0.40 104 8/11/2026
0.0.0.39 100 8/8/2026
0.0.0.38 118 8/8/2026
0.0.0.37 105 8/8/2026
0.0.0.36 104 8/8/2026
0.0.0.35 109 8/8/2026
0.0.0.34 109 8/7/2026
0.0.0.33 144 8/5/2026
0.0.0.32 159 7/27/2026
0.0.0.31 100 7/27/2026
0.0.0.30 109 7/27/2026
0.0.0.29 107 7/26/2026
0.0.0.27 111 7/26/2026
0.0.0.26 117 7/26/2026
0.0.0.25 205 7/2/2026
0.0.0.24 108 7/1/2026
0.0.0.22 130 7/1/2026
Loading failed