C# Academy · 课时

SignalR 中心与连接

创建 SignalR 中心,在 ASP.NET Core 中映射它,并从 JavaScript 和 .NET 客户端建立 WebSocket 连接。

第 1 / 4 课12 个步骤

SignalR 中心与连接 是 CoddyKit 上的免费 C# Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

什么是 SignalR?

SignalR 是一个 ASP.NET Core 库,用于在服务器与客户端之间实现实时双向通信。它会根据双方支持的功能,自动选择最佳传输方式:WebSockets、服务器发送事件或长轮询。

设置 SignalR

将 SignalR 添加到服务中,并映射一个中心端点。中心是负责处理客户端连接和方法调用的类。

builder.Services.AddSignalR();

var app = builder.Build();

app.UseCors("AllowAll");
app.MapHub<ChatHub>("/hubs/chat");

app.Run();

创建中心

继承 Hub。中心方法由客户端调用。Context 属性提供连接信息,而 Clients 允许您发送消息。

using Microsoft.AspNetCore.SignalR;

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        // Broadcast to ALL connected clients
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }

    public override async Task OnConnectedAsync()
    {
        await Clients.Caller.SendAsync("Welcome",
            $"Connected as {Context.ConnectionId}");
        await base.OnConnectedAsync();
    }
}

JavaScript Client

官方 SignalR JavaScript client 会构建连接、注册事件处理程序并启动连接。中心上定义的方法可以从 JavaScript 调用。

// npm install @microsoft/signalr
import * as signalR from "@microsoft/signalr";

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/chat")
    .withAutomaticReconnect()
    .build();

connection.on("ReceiveMessage", (user, message) => {
    console.log(`${user}: ${message}`);
});

await connection.start();
await connection.invoke("SendMessage", "Alice", "Hello!");

.NET SignalR Client

.NET client 的工作方式相同,适用于服务之间的实时通信或桌面、移动应用。

// dotnet add package Microsoft.AspNetCore.SignalR.Client

var connection = new HubConnectionBuilder()
    .WithUrl("https://myapp.com/hubs/chat")
    .WithAutomaticReconnect()
    .Build();

connection.On<string, string>("ReceiveMessage", (user, msg) =>
    Console.WriteLine($"{user}: {msg}"));

await connection.StartAsync();
await connection.InvokeAsync("SendMessage", "Bot", "Connected!");

向特定 Clients 发送消息

Clients 属性提供了用于定位特定连接、调用方或除指定对象之外的所有已连接客户端的方法。

// To the caller only
await Clients.Caller.SendAsync("YouSaid", message);

// To a specific connection
await Clients.Client(connectionId).SendAsync("PrivateMsg", msg);

// To all except caller
await Clients.Others.SendAsync("ReceiveMessage", user, message);

// To multiple specific connections
await Clients.Clients(new[] { id1, id2 })
             .SendAsync("DirectMsg", msg);

中心上下文:从中心外部发送消息

将 IHubContext<T> 注入服务或后台工作程序,即可从中心类外部发送消息,这对于服务器发起的推送至关重要。

public class NotificationService
{
    private readonly IHubContext<ChatHub> _hub;

    public NotificationService(IHubContext<ChatHub> hub) => _hub = hub;

    public async Task BroadcastAlertAsync(string alert)
    {
        // Send to all clients from a background service
        await _hub.Clients.All.SendAsync("SystemAlert", alert);
    }
}

连接生命周期事件

重写 OnConnectedAsync 和 OnDisconnectedAsync,以跟踪连接、维护状态或清理资源。

public override async Task OnConnectedAsync()
{
    _connections.TryAdd(Context.ConnectionId, GetUserName());
    await Clients.All.SendAsync("UserJoined", GetUserName());
    await base.OnConnectedAsync();
}

public override async Task OnDisconnectedAsync(Exception? ex)
{
    _connections.TryRemove(Context.ConnectionId, out var user);
    await Clients.All.SendAsync("UserLeft", user);
    await base.OnDisconnectedAsync(ex);
}

private string GetUserName() =>
    Context.User?.Identity?.Name ?? Context.ConnectionId;

自动重新连接

在 client 上启用自动重新连接,以便妥善处理短暂的断开连接。您可以自定义重试延迟。

// JavaScript client
const conn = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/chat")
    .withAutomaticReconnect([0, 2000, 5000, 10000, 30000]) // retry delays in ms
    .build();

conn.onreconnecting(err => console.warn("Reconnecting...", err));
conn.onreconnected(id  => console.log("Reconnected:",    id));
conn.onclose(err       => console.error("Disconnected:", err));

使用 SignalR 进行身份验证

SignalR 遵循 ASP.NET Core 身份验证中间件。将 [Authorize] 添加到中心类,或使用支持查询字符串令牌的 JWT handler(WebSocket 身份验证所必需)。

[Authorize]
public class PrivateHub : Hub
{
    public Task SendMessage(string msg)
    {
        var user = Context.User!.Identity!.Name;
        return Clients.All.SendAsync("Msg", user, msg);
    }
}

// JWT via query string (WebSocket requirement):
builder.Services.AddAuthentication().AddJwtBearer(opt =>
{
    opt.Events = new JwtBearerEvents
    {
        OnMessageReceived = ctx =>
        {
            var token = ctx.Request.Query["access_token"];
            if (!string.IsNullOrEmpty(token))
                ctx.Token = token;
            return Task.CompletedTask;
        }
    };
});

快速检查

如何从后台服务(中心类外部)发送 SignalR 消息?

回顾:SignalR 中心与连接

要点:

  • SignalR 会自动选择最佳传输方式(WebSockets、SSE、长轮询)
  • 中心方法可由客户端调用;Clients.* 用于定位特定接收者
  • 注入 IHubContext<T>,即可从中心外部推送消息
  • 重写 OnConnectedAsync/OnDisconnectedAsync 以管理生命周期
  • 使用 withAutomaticReconnect() 构建具有弹性的 client 连接
  • WebSocket 连接必须通过查询字符串使用 JWT 身份验证
免费开始

用 AI 导师学习 C# — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
93
课程
346

常见问题解答

「SignalR 中心与连接」课时是免费的吗?

是的 — 「SignalR 中心与连接」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「SignalR 中心与连接」这节课中我会学到什么?

创建 SignalR 中心,在 ASP.NET Core 中映射它,并从 JavaScript 和 .NET 客户端建立 WebSocket 连接。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「SignalR 中心与连接」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. SignalR 中心与连接
  2. 组、用户与连接管理
  3. 强类型中心
  4. 使用 Redis 后端扩展
← 返回 C# Academy