.NET中的WebSocket:客户端-服务器实时通信指南

本文探讨了如何在 .NET 应用程序中实现 WebSocket 这一功能强大的全双工通信协议。本文包括设置 WebSocket 服务器、创建客户端以及使用 System.Net.WebSockets 命名空间处理实时数据交换。无论您是要构建聊天应用程序、实时通知还是实时仪表盘,本文都将为您提供在 .NET 项目中利用 WebSocket 实现无缝双向通信的工具和知识。

WebSocket 是一种通过单个 TCP 连接提供全双工通信通道的通信协议。它常用于 Web 应用程序中客户端与服务器之间的实时通信。在 .NET 中,您可以使用 System.Net.WebSockets 命名空间来实现 WebSocket 功能,该命名空间提供了用于处理 WebSockets 的类。

高级场景

  • 身份验证:您可以使用令牌或 cookie 来验证 WebSocket 连接。
  • 可扩展性:对于大型应用程序,请考虑使用SignalR之类的库,它抽象了 WebSocket 通信并提供自动重新连接和回退传输等附加功能。
  • 二进制数据:WebSocket 支持二进制数据传输,这对于发送文件或其他非文本数据很有用。

在 .NET 中实现 WebSocket 的分步指南

步骤 1:创建一个新的 .NET 8 Web API 项目

在PowerShell 或命令提示符中运行以下命令:

dotnet new web -n WebSocketServer
cd WebSocketServer

这将创建一个名为 WebSocketServer 的新 ASP.NET Core Web API 项目。

步骤 2:安装所需的依赖项

尽管 .NET Core 默认包含 WebSocket 支持,但请确保您拥有最新的 .NET 8 SDK。

步骤 3:实现 WebSocket 中间件

创建一个新文件夹Middlewares并添加以下类:Middlewares/WebSocketMiddleware.cs

using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;

namespace WebSocketServer.Middlewares
{
    public class WSMiddleware
    {
        private readonly RequestDelegate _next;
        private static readonly ConcurrentDictionary<WebSocket, byte> _sockets = new();

        public WSMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path == "/ws" && context.WebSockets.IsWebSocketRequest)
            {
                using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                _sockets.TryAdd(webSocket, default);
                await ReceiveMessages(webSocket);
            }
            else
            {
                await _next(context);
            }
        }

        private async Task ReceiveMessages(WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];

            try
            {
                while (webSocket.State == WebSocketState.Open)
                {
                    var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        _sockets.TryRemove(webSocket, out _);
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by client", CancellationToken.None);
                        break;
                    }

                    string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    await BroadcastMessage(message);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
                _sockets.TryRemove(webSocket, out _);
            }
        }

        private async Task BroadcastMessage(string message)
        {
            var bytes = Encoding.UTF8.GetBytes(message);
            var buffer = new ArraySegment<byte>(bytes);

            foreach (var socket in _sockets.Keys)
            {
                if (socket.State == WebSocketState.Open)
                {
                    await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                }
            }
        }
    }
}

步骤 4:在 Program.cs 中注册中间件

修改 Program.cs 以注册 WebSockets 和中间件。

using Microsoft.AspNetCore.WebSockets;
using System.Net.WebSockets;
using System.Text;
using WebSocketServer.Middlewares;

var builder = WebApplication.CreateBuilder(args);

//builder.Services.AddWebSockets(options =>
//{
//    options.KeepAliveInterval = TimeSpan.FromSeconds(30);
//});


var app = builder.Build();

app.UseWebSockets(); // 启用 WebSocket 支持

app.UseMiddleware<WSMiddleware>();

app.MapGet("/", () => "Hello World!");

app.Run();

步骤 5:运行 WebSocket 服务器

现在,构建并运行项目:

dotnet run

默认情况下,服务器在http://localhost:5000上运行。

.NET中的WebSocket:客户端-服务器实时通信指南

使用postman :

.NET中的WebSocket:客户端-服务器实时通信指南

步骤 6:使用 WebSocket 客户端进行测试

1. 创建一个新的 .NET 控制台应用程序

dotnet new  console -n WebSocketClient
 cd WebSocketClient

2. 实现 WebSocket 客户端代码

Program.cs 的内容替换为以下代码:

using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;

namespace WebSocketServer.Middlewares
{
    public class WSMiddleware
    {
        private readonly RequestDelegate _next;
        private static readonly ConcurrentDictionary<WebSocket, byte> _sockets = new();

        public WSMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path == "/ws" && context.WebSockets.IsWebSocketRequest)
            {
                using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                _sockets.TryAdd(webSocket, default);
                await ReceiveMessages(webSocket);
            }
            else
            {
                await _next(context);
            }
        }

        private async Task ReceiveMessages(WebSocket webSocket)
        {
            var buffer = new byte[1024 * 4];

            try
            {
                while (webSocket.State == WebSocketState.Open)
                {
                    var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        _sockets.TryRemove(webSocket, out _);
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by client", CancellationToken.None);
                        break;
                    }

                    string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                    await BroadcastMessage(message);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
                _sockets.TryRemove(webSocket, out _);
            }
        }

        private async Task BroadcastMessage(string message)
        {
            var bytes = Encoding.UTF8.GetBytes(message);
            var buffer = new ArraySegment<byte>(bytes);

            foreach (var socket in _sockets.Keys)
            {
                if (socket.State == WebSocketState.Open)
                {
                    await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                }
            }
        }
    }
}

3. 运行项目并检查输出

.NET中的WebSocket:客户端-服务器实时通信指南

客户端:

.NET中的WebSocket:客户端-服务器实时通信指南

项目地址演示:https://github.com/hasanmonsur/WebSocket-in-.NET

结论

.NET 中的 WebSocket 提供了一种强大的解决方案,可实现客户端和服务器之间的实时双向通信,使其成为实时聊天、通知和实时数据流等应用程序的理想选择。通过利用System.Net.WebSockets命名空间,开发人员可以轻松构建高效且可扩展的实时系统。但是,如果您正在寻找更高级别的抽象或自动重新连接和回退传输等附加功能,请考虑探索SignalR,这是一个在 .NET 中的 WebSocket 之上构建的强大库。

作者:Md. Hasan Monsur

本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/im/56238.html

(0)

相关推荐

发表回复

登录后才能评论