ASP .NET CORE 6 项目实现WebSocket通信实践

ops/2024/9/21 10:20:11/

一、简介

        WebSocket 是一种计算机通信协议,提供了全双工通信通道,特别适用于需要频繁更新数据的应用,如实时聊天、在线游戏和股票行情等。它在 Web 应用中有着广泛的应用,因为它能够在客户端和服务器之间建立持久连接,从而实现低延迟、高效的数据传输。

二、WebSocket 原理

  1. 握手过程

    • 客户端发起 HTTP 请求,通过 Upgrade 头部字段请求升级到 WebSocket 协议。
    • 服务器接收到请求后,如果支持 WebSocket,则返回一个 101 状态码响应,表示协议切换成功。
  2. 建立连接

    • 握手成功后,客户端和服务器之间建立了一条持久连接,可以通过这个连接进行双向通信。
  3. 数据传输

    • 数据以帧(frame)的形式传输,每个帧包含一个固定的头部和可变长度的数据部分。
    • 帧可以是文本帧、二进制帧、关闭帧、Ping 帧或 Pong 帧。
  4. 关闭连接

    • 任一方都可以发送关闭帧来终止连接,另一方接收到关闭帧后也会发送一个关闭帧作为响应,然后连接关闭。

三、WebSocket 的作用

  1. 实时通信

    • WebSocket 提供了低延迟的双向通信,非常适合实时应用,如在线聊天、协作编辑和多人游戏等。
  2. 减少网络开销

    • 与传统的轮询方式相比,WebSocket 减少了不必要的 HTTP 请求和响应,从而降低了网络开销和服务器负载。
  3. 高效的数据传输

    • WebSocket 使用较小的头部信息,并且在连接建立后无需重复握手过程,使得数据传输更加高效。
  4. 保持长连接

    • 一旦建立连接,客户端和服务器之间可以持续通信,不需要频繁重新建立连接。
  5. 跨平台支持

    • WebSocket 被广泛支持,包括现代浏览器、移动设备和各种服务器框架,使其成为构建跨平台实时应用的理想选择。

四、项目实践 

1、新建WEB API 项目
2、新增WebStock拦截中间件:WebSocketMiddleware.cs
public class WebSocketMiddleware
{private readonly RequestDelegate _requestDelegate;public WebSocketMiddleware(RequestDelegate requestDelegate){_requestDelegate=requestDelegate;}public async Task InvokeAsync(HttpContext context){if (context.Request.Path == "/ws" && context.WebSockets.IsWebSocketRequest == true) { using(var webSocket = await context.WebSockets.AcceptWebSocketAsync()){await Echo(webSocket);}}else{await _requestDelegate(context);}}private async Task Echo(WebSocket webSocket){//封装数组片段:ArraySegment<T> 封装了一个数组及其指定的范围(起始索引和长度),使得可以对数组的某一部分进行操作,而不需要复制数组var buffer = new byte[1024 * 4];WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);while(!result.CloseStatus.HasValue){              var receivedMessage = Encoding.UTF8.GetString(buffer);Console.WriteLine(receivedMessage);//回显:在网络通信中,"Echo" 表示将接收到的数据原样返回给发送方var responseMessage = $"Echo:{receivedMessage}";var bytesToSend = Encoding.UTF8.GetBytes(responseMessage);await webSocket.SendAsync(new ArraySegment<byte>(bytesToSend),result.MessageType,result.EndOfMessage,CancellationToken.None);result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);}            await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);        }      
}
3、Program程序入口注册使用WebStock中间件:
//添加WebSocket支持
app.UseWebSockets();
app.UseMiddleware<WebSocketMiddleware>();
4、新建WebStock控制器,用于测试WebStock通信:
public class WebSocketController : ControllerBase
{// GET: api/<WebSocketController>[HttpGet("Requset")]public async Task<IActionResult> Resquest(){//using MiniProfiler.Current.Step("Web Stock request");using (MiniProfiler.Current.Step("Web Stock request"))using (ClientWebSocket webSocket = new ClientWebSocket()){Uri uri = new Uri("ws://localhost:8084/ws");//创建连接await webSocket.ConnectAsync(uri, CancellationToken.None);Console.WriteLine("webSocker Connect Successfully!");//发送消息string sendMessage = "你好,我是WebSocket请求者!";var bytes = Encoding.UTF8.GetBytes(sendMessage);await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);Console.WriteLine($"Send:{sendMessage}");//接收消息byte[] buffer = new byte[1024 * 4];await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);var receiveMessage = Encoding.UTF8.GetString(buffer);Console.WriteLine($"Receive:{receiveMessage}");//关闭连接await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);Console.WriteLine("webSocket Close Successfully");}return Ok();}
 5、测试

        启动api,开启Swagger支持,使用Swagger对WebStock通信发起请求,查看控制台输出。

五、总结

        总之,WebSocket 通过提供高效、低延迟的双向通信机制,极大地提升了 Web 应用的实时性能和用户体验。


http://www.ppmy.cn/ops/113736.html

相关文章

第二百三十九节 JPA教程 - JPA一对一延迟加载示例

JPA教程 - JPA一对一延迟加载示例 以下代码显示如何使用延迟加载设置执行一对一映射。 OneToOne(fetchLAZY)private Department department;例子 下面的代码来自Person.java。 package cn.w3cschool.common; import javax.persistence.Entity; import javax.persistence.Gene…

Spring Boot校园管理系统:技术选型与架构设计

第2章相关技术 2.1 B/S架构 B/S结构的特点也非常多&#xff0c;例如在很多浏览器中都可以做出信号请求。并且可以适当的减轻用户的工作量&#xff0c;通过对客户端安装或者是配置少量的运行软件就能够逐步减少用户的工作量&#xff0c;这些功能的操作主要是由服务器来进行控制的…

Vue接入高德地图并实现基本的路线规划功能

目录 一、申请密钥 二、安装依赖 三、代码实现 四、运行截图 五、官方文档 一、申请密钥 登录高德开放平台&#xff0c;点击我的应用&#xff0c;先添加新应用&#xff0c;然后再添加Key。 如图所示填写对应的信息&#xff0c;系统就会自动生成。 二、安装依赖 npm i am…

PMP--二模--解题--41-50

文章目录 11.风险管理--风险代表对将来问题的预判&#xff0c;问题代表对过去问题事件的跟踪&#xff1b;两者联系&#xff1a;风险发生后会变成问题&#xff0c;而问题可能导致新的风险。41、 [单选] 在项目会议期间&#xff0c;一个团队发现三个月前关闭的问题仍然处于活跃状…

PyQt / PySide + Pywin32 + ctypes 自定义标题栏窗口 + 完全还原 Windows 原生窗口边框特效项目

项目地址&#xff1a; GitHub - github201014/PyQt-NativeWindow: A class of window include nativeEvent, use PySide or PyQt and Pywin32 and ctypesA class of window include nativeEvent, use PySide or PyQt and Pywin32 and ctypes - github201014/PyQt-NativeWindow…

WPF 中的线程池

WPF 中的线程池 在 WPF 中&#xff0c;虽然应用程序主要运行在 UI 线程上&#xff0c;但我们可以使用 线程池 来执行后台任务而不会阻塞 UI 线程。WPF 中常用的线程池是 .NET 线程池&#xff0c;可以通过 ThreadPool 类或 Task 来管理后台任务。以下是 WPF 中如何使用线程池及…

WPF入门教学四 WPF控件概述

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;控件是构建用户界面的基本元素。它们使得开发人员能够创建出功能丰富、交互性强的应用程序。本部分将概述WPF中的控件&#xff0c;并介绍一些常用的控件及其基本用法。 WPF控件概述 WPF提供了多种…

Java 计算两个日期相差

java 8 比较日期核心 api ChronoUnit 可比较 年、月、周、日、时、分、秒、毫秒、微秒、纳秒 import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal;public class DateUtil {public st…