既然有 HTTP 协议,为什么还要有 WebSocket?(计算机网络)

看起来服务器主动发消息给客户端的场景,是怎么做到的?

使用 HTTP 不断轮询

怎么样才能在用户不做任何操作的情况下,网页能收到消息并发生变更。

最常见的解决方案是,网页的前端代码里不断定时发 HTTP 请求到服务器,服务器收到请求后给客户端响应消息。

这其实时一种「」服务器推的形式。

它其实并不是服务器主动发消息到客户端,而是客户端自己不断偷偷请求服务器,只是用户无感知而已。

用这种方式的场景也有很多,最常见的就是扫码登录

登录页面二维码出现之后,前端网页根本不知道用户扫没扫,于是不断去向后端服务器询问,看有没有人扫过这个码。而且是以大概 1 到 2 秒的间隔去不断发出请求,这样可以保证用户在扫码后能在 1 到 2 秒内得到及时的反馈,不至于等太久

但这样,会有两个比较明显的问题:

  • 当你打开 F12 页面时,你会发现满屏的 HTTP 请求。虽然很小,但这其实也消耗带宽,同时也会增加下游服务器的负担。
  • 最坏情况下,用户在扫码后,需要等个 1~2 秒,正好才触发下一次 HTTP 请求,然后才跳转页面,用户会感到明显的卡顿

使用起来的体验就是,二维码出现后,手机扫一扫,然后在手机上点个确认,这时候卡顿等个 1~2 秒,页面才跳转。

那么问题又来了,有没有更好的解决方案?

有,而且实现起来成本还非常低。

长轮询

HTTP 请求发出后,一般会给服务器留一定的时间做响应,比如 3 秒,规定时间内没返回,就认为是超时。

如果我们的 HTTP 请求将超时设置的很大,比如 30 秒,在这 30 秒内只要服务器收到了扫码请求,就立马返回给客户端网页。如果超时,那就立马发起下一次请求。

这样就减少了 HTTP 请求的个数,并且由于大部分情况下,用户都会在某个 30 秒的区间内做扫码操作,所以响应也是及时的。

像这种,在用户不感知的情况下,服务器将数据推送给浏览器的技术,就是所谓的服务器推送技术,它还有个毫不沾边的英文名,comet 技术,大家听过就好。

上面提到的两种解决方案(不断轮询和长轮询),本质上,其实还是客户端主动去取数据。

对于像扫码登录这样的简单场景还能用用。但如果是网页游戏呢,游戏一般会有大量的数据需要从服务器主动推送到客户端。这就需要WebSocket 了。

WebSocket是什么

我们知道 TCP 连接的两端,同一时间里双方都可以主动向对方发送数据。这就是所谓的全双工

而现在使用最广泛的HTTP/1.1,也是基于TCP协议的,同一时间里,客户端和服务器只能有一方主动发数据,这就是所谓的半双工

也就是说,好好的全双工 TCP,被 HTTP/1.1 用成了半双工。

这是由于 HTTP 协议设计之初,考虑的是看看网页文本的场景,能做到客户端发起请求再由服务器响应,就够了,根本就没考虑网页游戏这种,客户端和服务器之间都要互相主动发大量数据的场景。

所以,为了更好的支持这样的场景,我们需要另外一个基于TCP的新协议。于是新的应用层协议WebSocket就被设计出来了。

虽然名字带了个socket,但其实 socket 和 WebSocket 之间二者几乎毫无关系

怎么建立WebSocket连接

我们平时刷网页,一般都是在浏览器上刷的,这时候用的是 HTTP 协议,打开网页游戏,这时候就得切换成 WebSocket 协议

为了兼容这些使用场景。浏览器在 TCP 三次握手建立连接之后,都统一使用 HTTP 协议先进行一次通信。

  • 如果此时是普通的 HTTP 请求,那后续双方就还是老样子继续用普通 HTTP 协议进行交互。
  • 如果这时候是想建立 WebSocket 连接,就会在 HTTP 请求里带上一些特殊的header 头,如下:
Connection: Upgrade
Upgrade: WebSocket
Sec-WebSocket-Key: T2a6wZlAwhgQNqruZ2YUyg==\r\n

这些 header 头的意思是,浏览器想升级协议(Connection: Upgrade),并且想升级成 WebSocket 协议(Upgrade: WebSocket)。同时带上一段随机生成的 base64 码(Sec-WebSocket-Key),发给服务器。

如果服务器正好支持升级成 WebSocket 协议。就会走 WebSocket 握手流程,同时根据客户端生成的 base64 码,用某个公开的算法变成另一段字符串,放在 HTTP 响应的 Sec-WebSocket-Accept头里,同时带上101状态码,发回给浏览器。HTTP 的响应如下:

HTTP/1.1 101 Switching Protocols\r\n
Sec-WebSocket-Accept: iBJKv/ALIW2DobfoA4dmr3JHBCY=\r\n
Upgrade: WebSocket\r\n
Connection: Upgrade\r\n

101 确实不常见,它是指协议切换

之后,浏览器也用同样的公开算法将base64码转成另一段字符串,如果这段字符串跟服务器传回来的字符串一致,那验证通过。

就这样经历了一来一回两次 HTTP 握手,WebSocket就建立完成了,后续双方就可以使用 webscoket 的数据格式进行通信了。

先进行三次TCP握手建立连接,再在HTTP请求时根据需要看是否带上特殊的header头。

WebSocket的消息格式

数据包在WebSocket中被叫做,我们来看下它的数据格式长什么样子。 

我们只需要关注下面这几个字段。

opcode字段:这个是用来标志这是个什么类型的数据帧。比如。

  • 等于 1 ,是指text类型(string)的数据包
  • 等于 2 ,是二进制数据类型([]byte)的数据包
  • 等于 8 ,是关闭连接的信号

payload字段:存放的是我们真正想要传输的数据的长度,单位是字节。比如你要发送的数据是字符串"111",那它的长度就是3。

另外,可以看到,存放payload 长度的字段有好几个,我们既可以用最前面的7bit, 也可以用后面的7+16bit 或 7+64bit。

WebSocket会用最开始的7bit做标志位。不管接下来的数据有多大,都先读最先的7个bit,根据它的取值决定还要不要再读个 16bit 或 64bit。

  • 如果最开始的7bit的值是 0~125,那么它就表示了 payload 全部长度,只读最开始的7个bit就完事了。
  • 如果是126(0x7E)。那它表示payload的长度范围在 126~65535 之间,接下来还需要再读16bit。这16bit会包含payload的真实长度。

  • 以此类推

为防止粘包,WebSocket的数据格式也是数据头(内含payload长度) + payload data 的形式。

  • TCP 协议本身是全双工的,但我们最常用的 HTTP/1.1,虽然是基于 TCP 的协议,但它是半双工的,对于大部分需要服务器主动推送数据到客户端的场景,需要使用支持全双工的 WebSocket 协议。
  • 在 HTTP/1.1 里,只要客户端不问,服务端就不答。基于这样的特点,对于登录页面这样的简单场景,可以使用定时轮询或者长轮询的方式实现服务器推送(comet)的效果。
  • 对于客户端和服务端之间需要频繁交互的复杂场景,比如网页游戏,都可以考虑使用 WebSocket 协议。
  • WebSocket 和 socket 几乎没有任何关系,只是叫法相似。
  • 正因为各个浏览器都支持 HTTP协议,所以 WebSocket 会先利用HTTP协议加上一些特殊的 header 头进行握手升级操作,升级成功后就跟 HTTP 没有任何关系了,之后就用 WebSocket 的数据格式进行收发数据。

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

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

相关文章

联系媒体要有方法莫让投稿发文章只剩一声长叹相见恨晚

曾有一位饱经世事的前辈以一句至理名言警醒世人:“人之所以领悟道理,往往不是源于抽象的道理本身,而是生活给予的实实在在的挫折教训,如同撞南墙一般的痛彻觉醒;同样,让人豁然开朗的,也不是空洞的说教,而是实实在在的人生磨砺。”这一哲理,放在我们日常工作中亦有深刻的启示作用…

DHCP原理重磅来袭——走过路过不要错过

目录 一.DHCP来源 (1)手工分配缺点 (2)DHCP优点 二.DHCP设备调试 (1).基本配置: (2)接口地址池 1.开启DHCP功能 2.开启DHCP接口地址池功能 3.查看IP地址分配结果 (3)全局地…

Grafana实时监控minio的极简方法

背景 想监控一下minio的部分信息. 使用过程中需要关注的内容挺多的. 只看简单的node感觉已经不够了. 所以想监控易一下. ERLANG 复制 全屏 方式和方法 minio其实集成了prometheus 支持的监控指标 只需要在配置文件中放开就可以了. 虽然可以使用mc 的命令 create beartoken 但…

每日一题:c语言实现n的阶乘

目录 一、要求 二、代码 三、结果 一、要求 实现n的阶乘&#xff0c;已知n&#xff01;1*2*3*…*n 二、代码 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h>int main() {//初始化变量n为要求的几阶&#xff0c;jiecheng存储结果的&#xff0c;初始化为1…

AWTK 开源串口屏开发(15) - 通过 MODBUS 访问远程设备数据

在 AWTK 串口屏中&#xff0c;内置了 MODBUS Client 的模型&#xff0c;支持用 MODBUS 协议从远程设备获取数据。不用编写一行代码即可实现对远程设备数据的显示和修改。 1. 功能 不用编写代码&#xff0c;实现对远程设备数据的显示和修改。 2. 创建项目 从模板创建项目&am…

UGUI 进阶

UI事件监听接口 目前所有的控件都只提供了常用的事件监听列表 如果想做一些类似长按&#xff0c;双击&#xff0c;拖拽等功能是无法制作的 或者想让Image和Text&#xff0c;RawImage三大基础控件能够响应玩家输入也是无法制作的 而事件接口就是用来处理类似问题 让所有控件都…

【愚公系列】2024年03月 《AI智能化办公:ChatGPT使用方法与技巧从入门到精通》 015-用 ChatGPT 生成图片(Midjourney生图方法)

🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,51CTO博客专家等。 🏆《近期荣誉》:2022…

无人机+AI平安校园系统在天津大学成功运行

8月17日&#xff0c;北方天途航空联合天津大学&#xff0c;运用天途平安校园管理平台和大疆无人机场&#xff0c;开展无人机智能监控试点任务&#xff0c;协助学校保卫处监控人员和车辆情况&#xff0c;进行安全疏导和分流。 观看天途平安校园系统演示 现场工程师把天途平安校园…

一起来从Solidworks中导出URDF模型

这个博客是用来记录关于【从Solidworks中导出URDF模型】的学习历程&#xff1a; 相关课程链接见&#xff1a;如何从Solidworks导出URDF模型 • 古月 (guyuehome.com) 下面让我们一起开始吧&#xff01;&#xff01;&#xff01; 1. sw_urdf_exporter插件介绍 插件下载链接&…

2009-2023年上市公司华证ESG评级数据

2009-2023年上市公司华证ESG评级数据 1、时间&#xff1a;2009-2023年 2、指标&#xff1a;代码、名称 、华证ESG评级 3、来源&#xff1a;整理自wind 4、范围&#xff1a;上市公司 5、指标解释&#xff1a; 华证ESG评级是一种评估企业环境、社会和治理绩效的评级体系。…

搜维尔科技:SenseGlove Nova 允许以最简单的方式操作机器人并与物体交互

扩展 Robotics 和 QuarkXR 人机界面 XR 应用 Extend Robotics 利用扩展现实技术&#xff0c;让没有机器人专业知识的个人能够远程控制机器人。他们的 AMAS 解决方案使操作员能够不受地理限制地轻松控制机器人。 需要解决的挑战【搜维尔科技】 目前&#xff0c;操作机器人是一…

初学者必看!bashplotlib库让你轻松在Bash脚本中实现数据可视化

1. 是什么 bashplotlib 是一个 Python 库&#xff0c;用于在 Bash 脚本中生成数据可视化。它允许用户使用 Python 代码创建各种类型的图表&#xff0c;并将它们嵌入到 Bash 脚本中。bashplotlib 支持多种图表类型&#xff0c;包括条形图、折线图、饼图等。 2. 核心功能 bashplo…

Cookie 和 Session

1. 回顾 Cookie是浏览器在本地持久化存储结构的一种机制. 1.1 Cookie的数据从哪里来? 服务器返回给浏览器的. 1.2 Cookie的数据是什么样的? Cookie的数据是键值对结构. 并且这里的键值对都是程序员自定义的. 1.3 Cookie的作用是什么? Cookie可以在浏览器这边存储一些…

mysql 数据库基本操作

mysql 数据库基本操作 1、创建五张表 – user 表&#xff1a;后台用户表 – product 表&#xff1a;产品表 – account 表&#xff1a;客户账户表 – product_account 表 : 客户购买表 – customer 表 &#xff1a; 客户表 2、创建表 SQL 语句&#xff1a; 注意&#xff1a…

Figma使用问题(更新自己遇到的问题)

文章目录 前言一、如何安装插件&#xff1f;方法1&#xff1a;Figma Community / Figma中文社区方法2&#xff1a;菜单栏 二、图片倾斜插件使用1.Angle Mockups前提&#xff1a;执行过程&#xff1a; 三.中文字体插件&#xff08;宋体等&#xff09;Chinese Font Picker前提&am…

续-开发组件更新-提效工具分享

前言 小一个月没更新了&#xff0c;有各种各样的事啦&#xff0c;这一篇有点水吧。围绕两方面&#xff0c;开发组件更新以及IDEA插件的分享&#xff0c;题目和我一样水&#xff0c;有点像是日本轻小说取名了&#xff0c;整这么长。本篇的触动来源于&#xff0c;我今天偶然发现…

【保姆级讲解下Docker容器】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

openldap(一):简介和安装

目录 1 OpenLDAP简介1.1 LDAP介绍1、什么LDAP2、为什么要使用LDAP3、LDAP 的特点4、LDAP常用关键字5、LDAP的objectClass6、LADP使用场景 1.2 OpenLDAP介绍1、什么OpenLDAP2、OpenLDAP特点3、OpenLDAP的组件 2 OpenLDAP安装3 简单使用3.1 创建用户1、创建ou2、创建Group 3、创建…

NoSQL(非关系型数据库)之Redis的简介与安装

一、简介 1.1 关系型数据库与非关系型数据库 1.1.1 概念 1.1.2 区别 1.2 非关系型数据库产生背景 1.3 redis 简介 1.4 redis 优点 1.5 redis 快的原因 二、安装 2.1 关闭核心防护 2.2 安装相关依赖 2.3 解压软件包并进行编译安装 2.4 设置 Redis 服务所需相关配置文…

网络编程详解(select poll epoll reactor)

1. 客户端服务器建立连接过程 1.1 编写一个server的步骤是怎么样的&#xff1f; int main(){int listenfd, connfd;pid_t childpid;socklen_t clilen;struct sockaddr_in cliaddr, servaddr;listenfd socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr…