.NET WebSocket 核心原理初体验

上个月我写了《.NET gRPC核心功能初体验》, 里面使用gRPC双向流做了一个打乒乓球的Demo, [实时][双向]这两个标签是不是很熟悉,对, WebSockets也可以做实时双向通信。

本文将利用WebSockets(SignalR的一部分)搭建一个可双向通信的ASP.NETCore5应用。
(???? 预告:下期将着重对比gRPC和WebSockets的差异和使用场景)

我们先深入研究基本概念,以了解WebSockets幕后情况。

WebSockets简介

为支持在在客户端/服务端双向通信,引入了WebSockets.

HTTP 1.0:我们每次向服务器发送请求时都需要重新创建连接(关闭之前的连接)。
HTTP 1.1:新增keep-alive语法引入了持久连接机制, 至此连接可以被重用---这能减小通信延迟(因为服务器能感知客户端,并且不需要为每个请求重开握手过程)

WebSockets 依附于HTTP1.1协议的持久连接机制,因此如果你是第一次发起WebSockets连接,这实际是一个HTTP1.1请求,协商成功后开始全双工通信。

下图描述了初始化(握手),数据传输,关闭WebSockets的过程。

协议有两部分:握手和数据传输

握手

WebSocket与HTTP协议有良好兼容性。"握手"阶段采用Http协议,默认也是80/443端口,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

ws://example.com:80/some/path

简而言之,WebSocket连接基于单个端口上的HTTP(以TCP传输):

1.服务器在指定的端口(如80/443)上监听传入的TCP套接字连接2.客户端使用HTTP GET请求启动握手  (这就是“WebSockets”中的“Web”由来)。
在请求头中,客户端将要求服务器将连接Upgrade到WebSocket。3.服务器发送握手响应,通知客户端它将把协议从HTTP更改为WebSocket。4.客户端/服务器协商连接细节。如果条款不匹配,任何一方都可以退出。

GET /ws-endpoint HTTP/1.1
Host: example.com:80
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: L4kHN+1Bx7zKbxsDbqgzHw==
Sec-WebSocket-Version: 13

请注意:客户端发送Connection:UpgradeUpgrade:websocket请求头 服务端握手响应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: CTPN8jCb3BUjBjBtdjwSQCytuBo=

注意:服务端返回HTTP/1.1 101 Switching Protocols状态码,其他非101的状态码都指示握手失败。

数据传输

任意一方可以在任意时间发送消息,因为这是全双工通信协议。  

消息由一个或多个帧组成,一个帧可以是二进制、文本、控制帧(0x8 Close,0x9 Ping,0xA Pong)

.NETCore Server listening WebSockets

dotnet new webapi -n WebSocketsTutorial
dotnet add WebSocketsTutorial/ package Microsoft.AspNet.SignalR

为简化本次内容,我不会谈论SignalR(集线器和其他东西)。

本次将完全基于WebSocket通信。

app.UseWebSockets();

新增WebSocketsController.cs,添加如下代码:

using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace WebSocketsTutorial.Controllers
{[ApiController][Route("[controller]")]public class WebSocketsController : ControllerBase{private readonly ILogger<WebSocketsController> _logger;public WebSocketsController(ILogger<WebSocketsController> logger){_logger = logger;}[HttpGet("/ws")]public async Task Get(){if (HttpContext.WebSockets.IsWebSocketRequest){using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();_logger.Log(LogLevel.Information, "WebSocket connection established");await Echo(webSocket);}else{HttpContext.Response.StatusCode = 400;}}private async Task Echo(WebSocket webSocket){var buffer = new byte[1024 * 4];var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);_logger.Log(LogLevel.Information, "Message received from Client");while (!result.CloseStatus.HasValue){var serverMsg = Encoding.UTF8.GetBytes($"Server: Hello. You said: {Encoding.UTF8.GetString(buffer)}");await webSocket.SendAsync(new ArraySegment<byte>(serverMsg, 0, serverMsg.Length), result.MessageType, result.EndOfMessage, CancellationToken.None);_logger.Log(LogLevel.Information, "Message sent to Client");result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);_logger.Log(LogLevel.Information, "Message received from Client");}await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);_logger.Log(LogLevel.Information, "WebSocket connection closed");}}
}

在握手之后,服务端不需要等待客户端发起消息,就可以推送消息到客户端。

启动ASP.NET Core 服务端,程序在/ws路由地址监听WebSockets连接, 回发客户端发送过来的消息。

Browser client using WebSockets api

在浏览器Console编写js代码发起客户端websockets请求:

let webSocket = new WebSocket('wss://localhost:5001/ws');

在该请求的network- Messages tab页面可观察双向通信:

除此之外,服务器/客户端维护了pingpong机制,以确认客户端是否还存活。
如果您真的想看看这些数据包,使用WireShark之类的工具了解一下。

整个过程在Chrome-Network上只会有一个记录,所以你如果要看"握手过程", 也请在刚在的tab页面查看????。

最后

如果您有兴趣了解WebSocket的协议规范,请转至RFC 6455阅读。
这篇文章只是WebSockets的小试牛刀,还有许多我们可以讨论的其他事情,例如安全性,负载平衡,代理等✌️。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CvBlobDetector 新目标检测算法简析

CvBlobDetector用于检测和判定当前帧中的Blob是否是新产生的目标&#xff0c;方法如下&#xff1a;

原来这些流弊的老板,曾经还是牛逼的程序猿!

“生活就像巧克力&#xff0c;你永远不知道下一颗是什么味道”&#xff0c;这句话用在互联网最适合不过&#xff0c;互联网从人类里面创造了一批神&#xff0c;说起他们的名字无人不知&#xff0c;但是你可知道这些神曾经也只是一个名不见经传的程序员。一起来看看他们是怎么一…

phpstormp新建PHP保存在哪里_记一次windows配置PHP环境

前言因为疫情原因一直不能回学校&#xff0c;电脑还在学校宿舍&#xff0c;所以在笔记本上搭建PHP环境&#xff0c;总不能在家混吃等死吧。正文【0】安装Apache2.40-0:Apache的下载链接The Apache HTTP Server Project0-1:点击a number of third party vendors下载window版本0-…

通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务...

我个人认为Actor应该是Dapr里比较重头的部分也是Dapr一直在讲的所谓“stateful applications”真正具体的一个实现&#xff08;个人认为&#xff09;&#xff0c;上一章讲到有状态服务可能很多同学看到后的第一反应是“不就是个分布式缓存吗”。那今天就讲讲Actor,看看这个东西…

想转行人工智能?哈佛博士后有话说!

从17年开始&#xff0c;各大高校的数据科学与大数据技术专业持续火爆&#xff0c;2018年&#xff0c;北京大学、西安交通大学等高校更在本科阶段设立人工智能一级学科&#xff0c;中国顶尖人才的流向在悄然改变……据目前最新的数据显示&#xff0c;AI行业开发人员的月薪基本上…

转载标明出处用英语_英语原版阅读:At the beach

今天分享一篇阅读理解。可以学完一般现在时后进行同步阅读&#xff0c;也可以作为日常的阅读材料。每日10分钟英语阅读&#xff0c;养成习惯&#xff0c;孩子的英语学习不用愁。这篇文章的题目是At the beach图片来源于网络先来读文章&#xff1a;图片来源于网络1.In summer I …

12 月份 10 个新鲜的 jQuery 插件和教程

1. MASHA (Mark & Share) MASHA (Mark & Share 的缩写) 是一个可以让你分享网页部分内容的 JavaScript 库。 2. JScraft scroller 通过点击某个图片&#xff0c;该图将移到网页中央&#xff0c;其他相应的图片进行位置滑动。在线演示&#xff1a;here. 3. Windows-like…

大数据时代,如何才能提高自身竞争力?

暑假咻地一下过完啦&#xff0c;前几天&#xff0c;小天介绍了关于数模课程的开学季限时优惠&#xff08;传送门&#xff09;&#xff0c;今天要介绍的是python课程。接下来&#xff0c;小天来详细说明一下&#xff01;领取方式&#xff1a;公众号后台对话框回复“人工智能”免…

从容器到容器云,什么才是Kubernetes的本质?

这两年&#xff0c;Kubernetes 击败了 Swarm 和 Mesos&#xff0c;几乎成为容器编排的事实标准&#xff0c;BAT、滴滴、京东、头条等大厂&#xff0c;都争相把容器和 K8S 项目作为技术重心&#xff0c;试图“放长线钓大鱼”。就说阿里吧&#xff0c;目前基本所有业务都跑在云上…

Java 的日子屈指可数,这是真的吗?

斯坦福大学的计算机科学入门课采用JavaScript&#xff0c;摈弃Java&#xff0c;但是它的基数很大。年4月初&#xff0c;斯坦福大学开始试推行计算机科学入门课CS 106A的新版本。这个名为CS 106J的新版本用JavaScript来教&#xff0c;而不是用Java来教。斯坦福大学的官方网站解释…

5gh掌上云计算认证不通过_【众志成城战疫情】法官助理告诉你“移动微法院”、“掌上法庭”有多便捷、有多硬核~!...

今天中午&#xff0c;小编收到了一篇来自普定法院白岩法庭法官助理的投稿&#xff0c;她一方面告知小编白岩法庭今天上午通过微法院“掌上法庭”成功审理了一起买卖合同纠纷案纷&#xff0c;一方面强烈给小编安利了这个小程序&#xff0c;并且要求在本文结尾附上微法院的操作手…

“杀”一个程序员不需要用枪,改三次需求就可以了!

在很多软件公司&#xff0c;特别是一些创业型的团队中&#xff0c;对于这样的情景可能大家都很熟悉&#xff1a;项目经理或者产品经理&#xff08;产品狗&#xff09;口头或者简单记录一下软件产品的大致要做的功能&#xff0c;直接就让研发团队的兄弟&#xff08;程序猿&#…

WPF 仿QQ登录框翻转效果

突然发现qq登录窗体的翻转特效看起来不错&#xff0c;决定用wpf试试。主要知识点就是Viewport3D和AxisAngleRotation3D看一下效果&#xff1a;下面看一下代码&#xff1a;主要xaml代码&#xff1a;<UserControl x:Class"GQ.DirectContentSample"xmlns"http:/…

机器人J中WPR_优傲:协作机器人的未来在哪里?

2019年9月17日&#xff0c;第21届中国国际工业博览会于上海国家会展中心如期举办&#xff0c;期间优傲机器人(Universal Robots)公司推出新品&#xff0c;UR16e。有效载荷高达16kg&#xff0c;引起业界广泛的关注。优傲机器人总裁Jrgen von Hollen表示&#xff1a;“在当今不明…

你试过不用if撸代码吗?

试着不用if撸代码&#xff0c;是件很有趣的事&#xff0c;而且&#xff0c;万一你领会了什么是“数据即代码&#xff0c;代码即数据”呢&#xff1f;我在教新手编程时&#xff0c;喜欢给他们一些小小的挑战&#xff0c;比如&#xff1a;不使用if语句(或者三元运算符、switch语句…

NET问答: 对 Linq 中的 Union 和 Concat 的用法困惑

咨询区 Prasad Kanaparthi&#xff1a;我在使用 Union 和 Concat 上有一个困惑&#xff0c;从字面上理解&#xff1a;一个是并集&#xff0c;一个是连接&#xff0c;下面的例子就是我对这两个扩展方法的理解。static void Main(string[] args){var a1 (new[] { 1, 2 }).Union(…

中止是怎么用的_多士炉怎么用 使用多士炉注意事项

阅读本文前&#xff0c;请您先点击上面的蓝色字体&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到最新文章了。每天都有分享。完全是免费订阅&#xff0c;请放心关注。 …

国内 GitHub 造假黑色产业链曝光;开源开发者撤销对 ICE 禁用的决定

0、国内 GitHub 被爆造假&#xff0c;起底背后的黑色产业链作为全球最大的开源社区&#xff0c;GitHub 对于程序员群体而言像是空气般重要的存在&#xff0c;而互联网公司也会通过 GitHub 来进一步了解面试者的编程习惯&#xff0c;技术水平等。但最近知乎上有一篇《中国内地 G…

Azure data studio 跨平台数据库管理工具试用

最近折腾 azure sql database 的时候发现了微软的一款新的数据库管理工具&#xff1a;azure data studio。从名字上看 azure data studio 好像是专门为 azure 开发的&#xff0c;其实并不是这样的 。它同样支持对传统sql server的查询与管理。azure data studio 是一款跨平台数…

顺丰gis产品经理_线上面试季丰图科技—顺丰旗下专注GIS领域

WHITer内推——每天9点发布武汉优质互联网企业最新岗位内推机会。内推微信号&#xff1a;whxiaowai 内推邮箱&#xff1a;770554595qq.com01 Java高级开发工程师 12-25K点击查看职位详情 申请内推02高级python开发工程师 12-25K点击查看职位详情 申请内推03 物联网数据运营分析…