通信协议—WebSocket
一、WebSocket编程概念
1.1 什么是WebSocket
WebSocket 是一种全双工通信协议,允许在客户端(通常是浏览器)和服务器之间建立持久连接,以实现实时的双向通信。它是 HTML5 标准的一部分,相比传统的 HTTP 请求,WebSocket 提供了更低的延迟和更高的性能,特别适合于需要实时更新数据的应用程序,如在线聊天、实时监控、游戏等
1.2 WebSocket的基本使用步骤
1.2.1 )服务器端
1.2.1.1)使用System.Net.WebSocket命名空间
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Text;
1.2.1.2) 创建WebSocket服务器端点
public async Task HandleWebSocketConnection(HttpContext context)
{if (context.WebSockets.IsWebSocketRequest){WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();await EchoWebSocket(webSocket);}else{context.Response.StatusCode = 400;}
}
1.2.1.3)处理WebSocket消息
private async Task EchoWebSocket(WebSocket webSocket)
{var buffer = new byte[1024 * 4];WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);while (!result.CloseStatus.HasValue){// 发送接收到的消息回客户端await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);// 继续接收下一条消息result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);}// 关闭 WebSocket 连接await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
1.2.1.4)启动服务器
public static async Task Main(string[] args)
{var webSocketServer = new WebSocketServer();await webSocketServer.Start();
}
1.2.2 )客户端
1.2.2.1)使用System.Net.WebSocket.ClientWebSocket 命名空间
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Text;
1.2.2.2)创建WebSocket客户端并连接到服务器
public async Task ConnectToWebSocketServer()
{using (var clientWebSocket = new ClientWebSocket()){Uri serverUri = new Uri("ws://localhost:8080/ws");await clientWebSocket.ConnectAsync(serverUri, CancellationToken.None);await SendAndReceiveData(clientWebSocket);}
}
1.2.2.3)发送和接收数据
private async Task SendAndReceiveData(ClientWebSocket clientWebSocket)
{var buffer = new byte[1024 * 4];string message = "Hello, WebSocket Server!";var sendBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(message));await clientWebSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);WebSocketReceiveResult result = await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);Console.WriteLine($"Received: {receivedMessage}");
}
1.2.2.4)启动客户端
public static async Task Main(string[] args)
{var webSocketClient = new WebSocketClient();await webSocketClient.ConnectToWebSocketServer();
}
1.2.3) 运行步骤
1.2.3.1)先启动服务器程序,服务器将开始监听请求。
1.2.3.2)再启动客户端程序,客户端会连接到服务器并发送一条消息。
1.2.3.3)服务器接收到消息后,打印消息并回复。
1.2.3.4)客户端接收到服务器的回复并打印。
1.3 完整代码示例
1.3.1)服务器端
using System;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;namespace WebSocketServerExample
{public class WebSocketServer{private readonly IWebHost _webHost;public WebSocketServer(){_webHost = new WebHostBuilder().UseKestrel().ConfigureServices(services => services.AddRouting()).Configure(app =>{app.UseWebSockets();app.Use(async (context, next) =>{if (context.WebSockets.IsWebSocketRequest){WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();await EchoWebSocket(webSocket);}else{context.Response.StatusCode = 400;}});}).Build();}public async Task Start(){await _webHost.StartAsync();}private async Task EchoWebSocket(WebSocket webSocket){var buffer = new byte[1024 * 4];WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);while (!result.CloseStatus.HasValue){// 发送接收到的消息回客户端await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);// 继续接收下一条消息result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);}// 关闭 WebSocket 连接await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);}}class Program{static async Task Main(string[] args){var webSocketServer = new WebSocketServer();await webSocketServer.Start();}}
}// 代码解释
// 创建 WebSocket 服务器端点:
// app.UseWebSockets();:启用 WebSocket 中间件。
// context.WebSockets.IsWebSocketRequest:检查请求是否为 WebSocket 请求。
// context.WebSockets.AcceptWebSocketAsync():接受 WebSocket 请求并创建 WebSocket 对象。// 处理 WebSocket 消息:
// await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);:接收客户端发送的消息。
// await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);:将接收到的消息发送回客户端。
// await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);:当收到关闭请求时,关闭连接。
1.3.2)客户端
using System;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Text;namespace WebSocketClientExample
{public class WebSocketClient{public async Task ConnectToWebSocketServer(){using (var clientWebSocket = new ClientWebSocket()){Uri serverUri = new Uri("ws://localhost:8080/ws");await clientWebSocket.ConnectAsync(serverUri, CancellationToken.None);await SendAndReceiveData(clientWebSocket);}}private async Task SendAndReceiveData(ClientWebSocket clientWebSocket){var buffer = new byte[1024 * 4];string message = "Hello, WebSocket Server!";var sendBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(message));await clientWebSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);WebSocketReceiveResult result = await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);Console.WriteLine($"Received: {receivedMessage}");}}class Program{static async Task Main(string[] args){var webSocketClient = new WebSocketClient();await webSocketClient.ConnectToWebSocketServer();}}
}// 代码解释
// 创建 WebSocket 客户端并连接到服务器:
// new ClientWebSocket():创建 WebSocket 客户端对象。
// clientWebSocket.ConnectAsync(serverUri, CancellationToken.None);:连接到服务器。发送和接收数据:
// await clientWebSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);:向服务器发送消息。
// await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);:接收服务器的消息。
1.4 注意事项
1.4.1)端口号和URI : 确保服务器和客户端使用相同的端口号和URI路径
1.4.2)异常处理 :在实际应用中,需要添加适当的异常处理代码,例如处理连接失败、接收或发送消息时的异常等
1.4.3)多客户端处理 :上述服务器端代码仅处理一个客户端,对于多客户端场景,需要使用更复杂的逻辑,例如使用 ConcurrentDictionary 来管理多个客户端连接
相关文章:
通信协议—WebSocket
一、WebSocket编程概念 1.1 什么是WebSocket WebSocket 是一种全双工通信协议,允许在客户端(通常是浏览器)和服务器之间建立持久连接,以实现实时的双向通信。它是 HTML5 标准的一部分,相比传统的 HTTP 请求ÿ…...
helm推送到harbor私有库--http: server gave HTTP response to HTTPS client
harbor私有库访问的是http模式 harbor 2.8版本以上可以存储helm镜像 docker镜像推送的时候需要docker端配置insecure-registries 发现helm推送只能在harbor部署的本机使用localhost才能推送成功,即 helm push xxx.tgz oci://localhost:80/library 使用helm pus…...
数据结构——实验一·线性表
海~~欢迎来到Tubishu的博客🌸如果你也是一名在校大学生,正在寻找各种变成资源,那么你就来对地方啦🌟 Tubishu是一名计算机本科生,会不定期整理和分享学习中的优质资源,希望能为你的编程之路添砖加瓦⭐&…...
快速搭建深度学习环境(Linux:miniconda+pytorch+jupyter notebook)
本文基于服务器端环境展开,使用的虚拟终端为Xshell。 miniconda miniconda是Anaconda的轻量版,仅包含Conda和Python,如果只做深度学习,可使用miniconda。 [注]:Anaconda、Conda与Miniconda Conda:创建和管…...
OpenCV相机标定与3D重建(66)对立体匹配生成的视差图(disparity map)进行验证的函数validateDisparity()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 使用左右检查来验证视差。矩阵 “cost” 应该由立体对应算法计算。 cv::validateDisparity 函数是 OpenCV 库中用于对立体匹配生成的视差图&…...
2025年新开局!谁在引领汽车AI风潮?
汽车AI革命已来。 在2025年伊始开幕的CES展上,AI汽车、AI座舱无疑成为了今年汽车行业的最大热点。其中不少车企在2025年CES上展示了其新一代AI座舱,为下一代智能汽车的人机交互、场景创新率先打样。 其中,东软集团也携带AI驱动、大数据支撑…...
Spring自定义BeanPostProcessor实现bean的代理Java动态代理知识
上文:https://blog.csdn.net/qq_26437925/article/details/145241149 中大致了解了spring aop的代理的实现,其实就是有个BeanPostProcessor代理了bean对象。顺便复习下java代理相关知识 目录 自定义BeanPostProcessor实现aopJava动态代理知识动态代理的几…...
三篇物联网漏洞挖掘综述
由于物联网设备存在硬件资源受限、硬件复杂异构, 代码、文档未公开的问题, 物联网设备的漏洞挖掘存在较大的挑战: 硬件资源受限性: 通用动态二进分析技术需要在运行程序外围实施监控分析。由于物联网设备存储资源(存储)的受限性,…...
Pytorch深度学习指南 卷I --编程基础(A Beginner‘s Guide) 第1章 一个简单的回归
本章正式开始使用pytorch的接口来实现对应的numpy的学习的过程,来学习模型的实现,我们会介绍numpy是如何学习的,以及我们如何一步步的通过torch的接口来实现简单化的过程,优雅的展示我们的代码,已经我们的代码完成的事…...
【EXCEL_VBA_实战】多工作薄合并深入理解
工作背景:多个工作薄存在冲突的名称,需快速合并 困难点:工作表移动复制时,若有冲突的名称,会不断弹出对话框待人工确认 思路:利用代码确认弹出的对话框 关键代码:Application.DisplayAlerts …...
mysql之表的外键约束
MySQL表的外键约束详细介绍及代码示例 外键约束是数据库中用于维护数据完整性和一致性的重要机制。它确保一个表中的数据与另一个表中的数据相关联,防止无效的数据引用。本文将详细介绍了外键约束的各个方面,并通过具体的代码示例进行演示。 1. 外键约束…...
Tuning the Go HTTP Client Settings
记录一次Go HTTP Client TIME_WAIT的优化 业务流程 分析 通过容器监控发现服务到事件总线的负载均衡之间有大量的短链接,回看一下代码 发送请求的代码 func SendToKEvent(ev *KEvent) error {data, err : json.Marshal(ev.Data)if err ! nil {return err}log.Pri…...
第二十四课 Vue中子组件调用父组件数据
Vue中子组件调用父组件数据 Vue是不建议在不同的组件直接传递值的,我们需要使用props方法来进行组件间的值传递 子组件调用父组件数据 父模板的数据,子组件是无法直接调用的 无法直接调用 1)组件调用顶级对象中的data <div class&quo…...
Jenkins-pipeline语法说明
一. 简述: Jenkins Pipeline 是一种持续集成和持续交付(CI/CD)工具,它允许用户通过代码定义构建、测试和部署流程。 二. 关于jenkinsfile: 1. Sections部分: Pipeline里的Sections通常包含一个或多个Direc…...
小米Vela操作系统开源:AIoT时代的全新引擎
小米近日正式开源了其物联网嵌入式软件平台——Vela操作系统,并将其命名为OpenVela。这一举动在AIoT(人工智能物联网)领域掀起了不小的波澜,也为开发者们提供了一个强大的AI代码生成器和开发平台。OpenVela项目源代码已托管至GitH…...
NodeJs如何做API接口单元测试? --【elpis全栈项目】
NodeJs API接口单元测试 api单元测试需要用到的 assert:断言库 (还要一些断言库比如:Chai)supertest: 模拟http请求 简单的例子: const express require(express); const supertest require(supertest); const assert require(assert);…...
bundletool来特定设备规范的json安装aab包
1、获取自己设备的设备规范json java -jar ./bundletool.jar get-device-spec --outputj:/device-spec.json 2、根据设备规范生成apks包 java -jar ./bundletool.jar build-apks --device-specj:/device-spec.json --bundleapp-dev-release.aab --output随便的文件名.apks -…...
2024年第十五届蓝桥杯青少组国赛(c++)真题—快速分解质因数
快速分解质因数 完整题目和在线测评可点击下方链接前往: 快速分解质因数_C_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/cpp/show-3781.htmlhttps://www.hixinao.com/tiku/cpp/show-3781.html 若如其他赛事真题可自行前往题库中心查找,题…...
.Net Core微服务入门全纪录(四)——Ocelot-API网关(上)
系列文章目录 1、.Net Core微服务入门系列(一)——项目搭建 2、.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上) 3、.Net Core微服务入门全纪录(三)——Consul-服务注…...
chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确
问题描述 chrome游览器又一款JSON插件叫JSON Formatter,游览器GET请求调用接口时,如果返回的数据是json格式,则会自动格式化展示,类似这样: 但是今天突然发现怎么也格式化不了,打开一个json文件倒是可以格…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...
