在 .NET Core 和 React 中使用 WebSockets 和 SignalR 进行实时数据传输

对于需要即时更新和通知的应用程序来说,实时数据传输至关重要。在 .NET Core 中,WebSocket 和 SignalR 提供了强大的工具来实现客户端和服务器之间的实时通信。在本指南中,我们将探讨如何在 .NET Core 应用程序中使用 WebSocket 和 SignalR 实现实时数据传输。

什么是 WebSockets 和 SignalR?

WebSockets:

WebSockets 是一种通过单个 TCP 连接提供全双工通信通道的协议。它支持客户端和服务器之间的双向通信,允许异步发送和接收数据,而无需 HTTP 轮询的开销。

为什么选择 WebSocket?

1、实时通信:WebSockets 支持实时数据传输,使其成为需要即时更新的应用程序的理想选择,例如聊天应用程序、实时仪表板和在线游戏平台。

2、效率:与传统的 HTTP 轮询或长轮询技术不同,WebSocket 通过维持持久连接、最大限度地减少延迟和减少网络流量来降低开销。

3、全双工通信:WebSocket 支持双向同时传输数据,允许客户端和服务器独立发送和接收消息。

4、可扩展性:WebSockets 可以高效处理大量并发连接,适用于可扩展和高性能的应用程序。

WebSockets 的替代方案:

虽然 WebSocket 广泛用于实时通信,但有几种替代方案也提供类似的功能:

1、服务器发送事件 (SSE):SSE 是一种单向通信协议,允许服务器通过 HTTP 连接向客户端推送更新。与 WebSocket 不同,SSE 仅限于服务器到客户端的通信,不支持双向通信。

2、长轮询:长轮询是一种客户端向服务器发送请求的技术,服务器会保持连接打开,直到有新数据可用或发生超时。虽然长轮询可以实现实时更新,但由于频繁建立和关闭连接,其效率低于 WebSocket。

WebSockets 的优点和缺点:

优点:

• 实时更新:WebSockets 支持实时通信,为客户端提供即时更新。

• 效率:与轮询技术相比,WebSocket 减少了延迟和网络开销。

• 全双工通信:支持双向数据传输,允许客户端和服务器同时发送和接收消息。

• 可扩展性:WebSockets 可以高效处理大量并发连接,适合可扩展的应用程序。

缺点:

• 复杂性:实现和管理 WebSocket 连接比传统的 HTTP 通信更复杂。

• 浏览器支持:虽然现代浏览器支持 WebSockets,但旧版浏览器可能不支持,因此需要回退机制或其他方法。

• 防火墙问题:WebSockets 可能会面临限制性防火墙或阻止 WebSocket 流量的代理服务器的问题。

SignalR:

SignalR 是一个基于 WebSocket(以及其他传输机制)构建的高级库,可简化 .NET 应用程序中的实时 Web 功能。它抽象了管理连接的复杂性,并提供了一个简单的 API 用于向客户端广播消息并处理客户端与服务器之间的通信。

为什么选择 SignalR?

1、简化开发:SignalR 简化了管理 WebSocket 连接的复杂性,并提供了一个简单的 API 来实现 .NET 应用程序中的实时功能。它负责连接管理、消息路由和错误处理,使开发人员能够专注于应用程序逻辑。

2、跨平台支持:SignalR 支持服务器端 .NET 应用程序和客户端 JavaScript 框架,使其适合在 Web 应用程序、桌面应用程序和移动应用程序中构建实时功能。

3、可扩展性:SignalR 旨在随您的应用程序扩展,支持大量并发连接,并提供扩展到多台服务器或使用基于云的解决方案(如 Azure SignalR 服务)的选项。

4、回退机制:对于不支持 WebSocket 的客户端,SignalR 会自动回退到替代传输机制,例如服务器发送事件 (SSE) 或长轮询,确保跨浏览器和设备的广泛兼容性。

SignalR 的替代方案:

虽然 SignalR 是 .NET 应用程序中实时 Web 功能的热门选择,但也有几种替代方案提供类似的功能:

1、原始 WebSocket API:开发人员可以使用 .NET 或其他编程语言提供的原始 WebSocket API 来实现实时通信,而无需 SignalR 提供的抽象。但是,这种方法需要更多的手动配置,对开发人员来说可能不太方便。

2、第三方库:有一些第三方库可用于在 .NET 应用程序中实现实时通信,例如 .NET 的 Socket.IO 或 Fleck。这些库提供了额外的功能和灵活性,但可能需要付出更多努力来集成和维护。

SignalR 的优点和缺点:

优点:

• 简化开发:SignalR 提供了用于实现实时功能的高级 API,减少了开发时间和复杂性。

• 跨平台支持:SignalR 支持广泛的客户端,包括 Web 浏览器、桌面应用程序和移动设备。

• 可扩展性:SignalR 旨在随您的应用程序扩展,支持大量并发连接并提供扩展到多台服务器的选项。

• 回退机制:对于不支持 WebSockets 的客户端,SignalR 会自动回退到替代传输机制,确保广泛的兼容性。

缺点:

• 对 .NET Framework/Core 的依赖:SignalR 与 .NET 生态系统紧密耦合,因此不太适合使用其他技术构建的应用程序。

• 性能开销:虽然 SignalR 简化了开发,但与原始 WebSocket 实现相比,它可能会带来一些性能开销。

• 复杂性:SignalR 抽象了一些实时通信的复杂性,但在复杂场景中可能仍然需要额外的配置和故障排除。

为什么要使用实时数据传输?

实时数据传输对于需要实时更新的应用程序至关重要,例如:

• 聊天应用程序

• 实时仪表板和监控系统

• 协作文档编辑工具

• 在线游戏平台

• 股票市场跟踪应用程序

• 现场体育记分牌

在 .NET Core 中使用 SignalR 实现

步骤1:安装 SignalR

使用 NuGet 包管理器安装 SignalR 包:

otnet add package Microsoft.AspNetCore.SignalRadd package Microsoft.AspNetCore.SignalR

步骤2:创建 SignalR Hub

创建一个 SignalR 中心来管理客户端连接并处理消息广播。

using Microsoft.AspNetCore.SignalR;

using System.Threading.Tasks;

public class ChatHub : Hub

{

public async Task SendMessage(string user, string message)

{

await Clients.All.SendAsync("ReceiveMessage", user, message);

}

}

步骤3:在启动中配置 SignalR

在 Startup 类中配置 SignalR 以启用 WebSocket 支持并映射集线器端点。

public void ConfigureServices(IServiceCollection services)

{

services.AddSignalR();

}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

app.UseRouting();

app.UseEndpoints(endpoints =>

{

endpoints.MapHub<ChatHub>("/chatHub");

});

}

步骤 4:客户端集成

在客户端集成SignalR以建立连接并接收实时更新。

<!DOCTYPE html>

<html>

<head>

<title>SignalR Chat</title>

<script src="https://cdnjs.cloudflare.com/ajax/libs/signalr/5.0.0/signalr.min.js"></script>

</head>

<body>

<div id="messages"></div>

<input type="text" id="messageInput" />

<button οnclick="sendMessage()">Send</button>

<script>

const connection = new signalR.HubConnectionBuilder()

.withUrl("/chatHub")

.build();

connection.on("ReceiveMessage", (user, message) => {

document.getElementById("messages").innerHTML += `<p><strong>{user}\: {message}</p>`;

});

connection.start().then(() => {

console.log("Connected to SignalR hub");

}).catch((err) => {

console.error("Error connecting to SignalR hub:", err);

});

function sendMessage() {

const user = "User"; // Get user from input

const message = document.getElementById("messageInput").value;

connection.invoke("SendMessage", user, message);

}

</script>

</body>

</html>

让我们扩展这个示例,包括接收来自客户端的消息并提供包含后端和前端代码的端到端解决方案。

后端:带有 SignalR 的 ASP.NET Core Web API

步骤 1:创建 SignalR Hub

创建一个 SignalR 中心来管理客户端连接并处理消息广播。

using Microsoft.AspNetCore.SignalR;

using System.Threading.Tasks;

public class ChatHub : Hub

{

public async Task SendMessage(string user, string message)

{

await Clients.All.SendAsync("ReceiveMessage", user, message);

}

public void ReceiveMessage(string user, string message)

{

// Handle received message (e.g., save to database, process, etc.)

}

}

步骤2:在启动中配置 SignalR

在 Startup 类中配置 SignalR 以启用 WebSocket 支持并映射集线器端点。

public void ConfigureServices(IServiceCollection services)

{

services.AddSignalR();

}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

app.UseRouting();

app.UseEndpoints(endpoints =>

{

endpoints.MapHub<ChatHub>("/chatHub");

});

}

步骤3:创建用于接收消息的控制器

创建一个控制器来处理来自客户端的传入消息。

using Microsoft.AspNetCore.Mvc;

Route("api/\[controller\]")

ApiController

public class ChatController : ControllerBase

{

private readonly IHubContext<ChatHub> _hubContext;

public ChatController(IHubContext<ChatHub> hubContext)

{

_hubContext = hubContext;

}

HttpPost("ReceiveMessage")

public async Task<IActionResult> ReceiveMessage(string user, string message)

{

await _hubContext.Clients.All.SendAsync("ReceiveMessage", user, message);

return Ok();

}

}

前端:使用 SignalR 的 React UI

步骤1:安装 SignalR 客户端库

使用 npm 安装 JavaScript 的 SignalR 客户端库。

npm install @microsoft/signalr

步骤2:创建WebSocket连接

创建与 SignalR 集线器的 WebSocket 连接并处理传入消息。

import React, { useState, useEffect } from 'react';

import * as signalR from '@microsoft/signalr';

const Chat = () => {

const [messages, setMessages] = useState([]);

const [connection, setConnection] = useState(null);

useEffect(() => {

const newConnection = new signalR.HubConnectionBuilder()

.withUrl("/chatHub")

.build();

newConnection.on("ReceiveMessage", (user, message) => {

setMessages([...messages, { user, message }]);

});

newConnection.start()

.then(() => console.log("Connected to SignalR hub"))

.catch(error => console.error("Error connecting to SignalR hub:", error));

setConnection(newConnection);

}, []);

const sendMessage = () => {

const user = "User"; // Get user from input

const message = "Hello, SignalR!"; // Get message from input

connection.invoke("SendMessage", user, message)

.catch(error => console.error("Error sending message:", error));

};

return (

<div>

<div>

{messages.map((message, index) => (

<div key={index}>

<strong>{message.user}</strong>: {message.message}

</div>

))}

</div>

<input type="text" />

<button onClick={sendMessage}>Send</button>

</div>

);

};

export default Chat;

总结

在本指南中,我们探讨了如何在 .NET Core 应用程序中使用 WebSocket 和 SignalR 实现实时数据传输。利用 SignalR,您可以轻松实现客户端和服务器之间的实时通信,使其成为构建交互式协作 Web 应用程序的理想选择。无论您是构建聊天应用程序、实时仪表板还是多人游戏,SignalR 都能提供向用户提供实时更新所需的工具。

我们演示了如何在 .NET Core 后端和 React 前端使用 SignalR 实现实时消息传递。用户可以从前端发送消息,然后由后端 SignalR 中心接收并广播到所有连接的客户端。这种端到端解决方案为 Web 应用程序提供了无缝的实时消息传递体验。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。