当前位置:首页 > 科技  > 软件

别背八股文了,WebSocket 是什么,我劝你花几分钟让面试官惊艳!

来源: 责编: 时间:2024-06-05 17:39:25 86观看
导读前言作为前端工程师,我们几乎每天都在使用 ajax / fetch 请求与后端进行数据交互,这种基于请求-响应的通讯模式,我们再熟练不过了,无论是C端产品或者是B端产品,都离不开这种通讯模式。但是像即时通讯IM类场景,通常不会选择

前言

作为前端工程师,我们几乎每天都在使用 ajax / fetch 请求与后端进行数据交互,这种基于请求-响应的通讯模式,我们再熟练不过了,无论是C端产品或者是B端产品,都离不开这种通讯模式。但是像即时通讯IM类场景,通常不会选择这种“你来我回”的通信模式,而是会选择 WebSocket 这类的全双工通信模式。ZZO28资讯网——每日最新资讯28at.com

本文会带您全方位去了解一下 WebSocket 的本质,方便您搞清楚“Connection: Upgrade 是什么意思,为什么是它?”、“Upgrade: WebSocket 又是什么意思?这就可以双向通信了?”、“WebSocket 和 HTTP/TCP 到底有什么关联?八股文背了还是不理解”之类的问题,帮助您无论面试或工作时被问到 WebSocket 都能有更多细节可以聊,妥妥的一个加分项!ZZO28资讯网——每日最新资讯28at.com

最后通过一个在线聊天室实战案例带大家熟悉下 WebSocket 的全栈使用,可点击在线聊天室[3]进行体验。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

认识 WebSocket

WebSocket 是一种网络通信协议,它建立在 HTTP 之上,提供了在单个 TCP 连接上进行全双工通信的能力。这意味着服务器和客户端可以互相发送和接收消息,而不需要每次都重新建立连接。WebSocket 最初由 HTML5 规范定义,具体可以参考WebSockets Living Standard[4]。而现在,WebSocket 已被广泛支持并应用于各种应用,包括实时聊天、多人在线游戏、股票交易系统等需要实时数据更新的场景。ZZO28资讯网——每日最新资讯28at.com

WebSocket 的兼容性如何?

作为前端开发,对 API 的兼容性还是非常敏感的,我们先来看看 WebSocket 的兼容性怎么样。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

可以看到,主流浏览器都支持了 WebSocket,IE10 及以上版本也对 WebSocket 提供了完备的支持,所以我们可以大胆地使用起来!ZZO28资讯网——每日最新资讯28at.com

WebSocket 的前端用法

浏览器 JS 运行时提供了 WebSocket[5] 这个 API,可以用来创建和管理 WebSocket 连接。ZZO28资讯网——每日最新资讯28at.com

使用也非常简单,构造实例后只有几个简单的方法调用,一看就会。ZZO28资讯网——每日最新资讯28at.com

// 创建一个新的 WebSocket 连接const socket = new WebSocket('ws://your-websocket-server-url')// 监听连接打开socket.onopen = (e) => {  console.log('WebSocket is connected.')  // 连接打开后,你可以发送消息  socket.send('Hello Server!')}// 监听消息socket.onmessage = (e) => { console.log('Message from server: ', e.data) }// 监听关闭socket.onclose = (e) => { console.log('Connection closed.') }// 监听错误socket.onerror = (err) => { console.error('WebSocket Error: ', err) }// 如果你想主动关闭连接,可以调用 close 方法// socket.close()

wss:// 是 ws:// 的 TLS 加持版,可以类比于 https:// 和 http://ZZO28资讯网——每日最新资讯28at.com

Nodejs 原生支持 WebSocket 吗?

WebSocket 前端的使用非常简单,我自然会联想到:如果我做全栈开发,用 Nodejs 实现 WebSocket 服务端,有原生的模块可以支持吗?ZZO28资讯网——每日最新资讯28at.com

经过查询了解到,Node 原生模块中并未直接支持 WebSocket 服务端的开箱使用,一个比较流行的库是 ws[6]。ZZO28资讯网——每日最新资讯28at.com

那么 ws 这个库是怎么实现 WebSocket 服务端的呢?怎么才能和浏览器的 WebSocket 实现对接上?ZZO28资讯网——每日最新资讯28at.com

直接读源码肯定是看不懂的,即便看懂了一些过程调用,也是懵逼的,我们往下看。ZZO28资讯网——每日最新资讯28at.com

WebSocket 协议概览

我们知道,通讯是基于协议的,WebSocket 也有它的专属协议。ws 的实现它也是要遵循这个协议,才能和客户端实现匹配上,完成通讯。ZZO28资讯网——每日最新资讯28at.com

这个协议我们去哪里看呢?根据 wikipedia 的介绍,我们知道,WebSocket 的标准化是基于IETF 的 RFC 6455 WebSocket Protocol[7]。大致浏览后,我圈出了协议里一些值得关注的内容。阅读这类协议时,我们可以先挑重点看,对协议有一个基本的认识即可。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

我们了解到一些关键词:ZZO28资讯网——每日最新资讯28at.com

  1. 连接握手
  2. 怎么建立连接
  3. 数据发送和接收,数据帧
  4. 关闭握手
  5. 插件,相关 HTTP 头部字段

虽然有了一些关键词在脑海中,但我们对整个通讯过程肯定还有一连串疑问。带着疑问,我们继续往下看协议的具体内容。ZZO28资讯网——每日最新资讯28at.com

  1. 我们会了解到 WebSocket 出现的背景,它是为了解决什么,很显然,普通的 HTTP 请求不适合一些双向通信场景,比如聊天、股票、游戏等。
  2. 即便普通 HTTP 请求能通过一些业务设计满足双向通信需求,性能问题也很大,TCP 连接的开销等问题都要考虑在内。
  3. WebSocket 就是希望在一个 TCP 连接上,开辟双工通道,实现全双工实时通信。
  4. 之所以选择在 HTTP 协议的基础上去实现 WebSocket,也是一种权衡和取舍,可能会牺牲一些性能,但是也极大地复用了已有的网络基础设施,包括协议、安全、代理、认证等。

图片图片ZZO28资讯网——每日最新资讯28at.com

WebSocket 协议 - 连接握手

再往下翻一翻协议,我们能翻到最关键的部分,这也是面试里能和面试官吹的内容,请仔细看!ZZO28资讯网——每日最新资讯28at.com

很多人面试被问到 WebSocket,就说 WebSocket 可以双向通信,这是和 HTTP 最大的不同。讲道理,这种回复面试官已经听腻了。ZZO28资讯网——每日最新资讯28at.com

如果你能告诉面试官,WebSocket 的协议涉及到以下几个 HTTP 头部字段,并简述一下各个字段的简单含义,我相信你的面试绝对加分!ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

我们先看请求头:ZZO28资讯网——每日最新资讯28at.com

  • WebSocket 请求一定是 GET 类型的。
  • Origin: 浏览器客户端会带上,包含 Origin 是为了安全考虑,充分利用浏览器的同源策略。
  • Connection: Upgrade 和 Upgrade: websocket。这是客户端告知服务端需要升级协议,并且升级的协议为 websocket。
  • Sec-WebSocket-Key:由客户端(比如浏览器)随机生成,16位随机数经过 base64 编码后得到。响应头 Sec-WebSocket-Accept 是与它搭配使用的,用来确保请求的有效性和安全性。
  • Sec-WebSocket-Protocol:不是必选的。用来约定应用层面的子协议,使得客户端和服务器能够灵活地协商并选择一个双方都能理解的协议来进行通信。如果服务端选择使用某个子协议通信,则会在响应头中返回。

再看响应头:ZZO28资讯网——每日最新资讯28at.com

  • 服务端返回 101 Switching Protocols,代表握手成功,协议切换到 WebSocket。
  • Connection: Upgrade 和 Upgrade: websocket,用于告知客户端可以升级为 websocket 协议。
  • Sec-WebSocket-Accept:基于 Sec-WebSocket-Key 处理得到,处理公式如下,其中"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"是一个固定的字符串:
base64-encode(sha1(Sec-WebSocket-Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))

引用 wikipedia 的一张图,可以看得更清楚!ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

WebSocket 协议 - 数据帧

建立了连接握手后,WebSocket 就可以发送和接受消息数据了,消息是由一个或多个帧组成的。我们先看看这两张图了解一下数据帧的结构。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

其中 Opcode 是操作码,具体见下表。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

由于存在数据比较大的可能,这时需要切片传输,WebSocket 消息数据支持分片传输。ZZO28资讯网——每日最新资讯28at.com

  • 当 FIN = 1 且 OpCode ≠ 0 时,代表这一帧数据不是分片处理的。
  • 当 FIN = 0 时,如果 OpCode = 0,代表这一帧数据是某个分片的中间数据帧;如果 OpCode ≠ 0,代表这一帧数据是一个分片数据中的起始帧。

WebSocket 能发送文本数据或二进制数据,这个是体现在 OpCode 上。如果起始帧的 OpCode 是 1,则代表是文本数据;如果起始帧的 OpCode 是 2,则代表是二进制数据。ZZO28资讯网——每日最新资讯28at.com

WebSocket 协议 - 关闭连接

我们看看规范中,关闭握手这部分是怎么说的。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

WebSocket 任何一端都可以发起关闭连接。ZZO28资讯网——每日最新资讯28at.com

当一方准备关闭连接时,应该发送 Close Frame 开始关闭握手,之后不应该再发送任何数据;ZZO28资讯网——每日最新资讯28at.com

另一方收到 Close Frame 时,需要回复 Close Frame,并且准备释放资源,同时也应该丢弃后续从这个连接上可能接收到的数据。ZZO28资讯网——每日最新资讯28at.com

发起方收到 Close Frame 控制帧后,关闭连接释放资源,不再接收数据。ZZO28资讯网——每日最新资讯28at.com

这种 WebSocket 关闭握手机制也是在 TCP 握手机制上的一种补充,更好地保证端到端通信的可靠性!ZZO28资讯网——每日最新资讯28at.com

有的朋友可能会考虑到这个问题:当客户端发送 Close Frame 后,服务端正常接收到,并且回复 Close Frame,但是由于网络问题客户端没有服务端响应的 Close Frame,这种情况是怎么关闭 WebSocket 连接的?ZZO28资讯网——每日最新资讯28at.com

实际上,TCP 连接也有它的超时和重试机制,当一段时间内没有数据传输时,也会断开连接。所以我们无需担心这一点。ZZO28资讯网——每日最新资讯28at.com

当这种没有成功关闭握手但是关闭了 TCP 连接的情况发生时,onclose事件回调中收到的错误码应该是 1006,这一点可以在上面的表格中找到。ZZO28资讯网——每日最新资讯28at.com

正常关闭是 1000。ZZO28资讯网——每日最新资讯28at.com

在实际业务实现上,还会通过 ping-pong 之类的心跳检测机制来保证可靠性。ZZO28资讯网——每日最新资讯28at.com

回顾 ws 关键源码

有了这些知识储备后,再来看 ws 的实现源码,可能就会有头绪一点。ZZO28资讯网——每日最新资讯28at.com

当你看到这部分,你会知道它在校验头部字段是否符合协议要求,准备升级协议...ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

当你看到这个 101 状态码,你会恍然大悟:“哦,原来是在这里完成了协议的升级!”虽然还有些细节看不懂,但是无伤大雅!ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

当你看到这里时,你会知道,如果客户端尝试通过普通的 HTTP 请求来连接 WebSocket 服务,服务端应该返回 426 Upgrade Required 告诉客户端,“你该升级协议再跟我对话!”ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

本文不是源码解读,点到为止,我们往下看。ZZO28资讯网——每日最新资讯28at.com

为什么选择 Socket.IO

实际将 WebSocket 运用到生产环境时,我们一般不会直接使用 ws 这种协议实现库,而是会选择在应用层面进行了一些封装的库,比如 Socket.IO[8]。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

这是因为在 WebSocket 实际使用过程中,还有很多问题要考虑,比如心跳检测、优雅降级、房间隔离、命名空间隔离、API 的易用性等。而这些,Socket.IO 已经开箱支持。ZZO28资讯网——每日最新资讯28at.com

准确说,Socket.IO 并非是一个 WebSocket 实现,而是一个事件驱动的低延迟双向通讯方案。ZZO28资讯网——每日最新资讯28at.com

它的底层通讯不一定是基于 WebSocket 的,可能会根据情况选择 HTTP 长轮询、WebTransport[9]。ZZO28资讯网——每日最新资讯28at.com

WebTransport 是一个基于 HTTP/3 的通讯技术,可实现可靠通信和不可靠通信。HTTP/3 底层基于 Google 的 QUIC 协议,而 QUIC 协议是基于 UDP 的。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

Socket.IO 有它的约定和规则,或者叫协议,只要遵循这个协议,就能完成客户端和服务端的实现,所以你会看到,它也有多语言的实现,甚至在客户端还有小程序的实现。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

这个协议其实也就对应着Socket.IO 的底层引擎 Engine.IO[10]。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

虽然现在大部分浏览器都支持了 WebSocket,但是也不排除某些远古项目的存在,它必须运行在“古董”浏览器版本之上。Socket.IO 考虑到了这一点,它的自动优雅降级完美解决了这一问题。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

Socket.IO 的心跳检测机制和自动重连也是实际业务中必不可少的!ZZO28资讯网——每日最新资讯28at.com

更多的特性还有:ZZO28资讯网——每日最新资讯28at.com

  • 对话回调
  • 广播
  • 房间
  • 命名空间多路复用
  • ...

Socket.IO 的通讯过程

当我们打开一个 Socket.IO 的客户端页面时,会发现 Network 里发出了多个请求,在 101 websocket 连接建立之前,有 4 个 xhr 请求,其中还有一个是 POST 请求。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

Socket.IO 在升级机制中解释了这一点,直接建立可靠可用的 WebSocket 连接并非一件很轻松的事情,通常从 HTTP 开始平滑升级到 WebSocket,对连接的可靠性和用户体验来说是更好的。ZZO28资讯网——每日最新资讯28at.com

升级协议会经历这么一些步骤,对应着我们在上面看到的几个 Network 请求。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

我这个项目开始得很早,所以EIO=3,代表协议版本号是3,目前 Engine.IO 已经升级到版本4了。ZZO28资讯网——每日最新资讯28at.com

在 Socket.IO 的 HTTP 长轮询模式中,使用长时间运行的 GET 请求接收数据,使用短期运行的 POST 请求发送数据。ZZO28资讯网——每日最新资讯28at.com

了解了这些机制,并且查看 API 用法后,就可以开始运用了,一些高级用法可以在使用过程中再去探索!ZZO28资讯网——每日最新资讯28at.com

聊天室的全栈实现

基于以上理解,我们开始搭建博客项目中的聊天室功能,我们会实现这些主要能力:ZZO28资讯网——每日最新资讯28at.com

  • 成功创建 Socket.IO 连接
  • 展示聊天室的系统通知信息(涉及到单播和广播)
  • 聊天对话功能(广播)

我们首先把依赖安装好,客户端使用socket.io-client[11],服务端使用socket.io[12]即可。ZZO28资讯网——每日最新资讯28at.com

服务端开启 WebSocket 服务

第一步是把 WebSocket 服务启动。由于本项目开始较早,socket.io 版本是 2.5,大家对照文档的时候按 2.x 文档看就好。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

socket.io 可以利用已经存在的 HTTP 服务,由于项目是用 Express 搭建的,我们直接与 Express 共享一个 HTTP 服务即可。ZZO28资讯网——每日最新资讯28at.com

io 实例化后,监听到 connection 事件就代表有客户端过来了,可以开始干活了。我这里是把聊天室相关的逻辑都放在了 chatroom 这个命名空间下。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

of 的作用就是初始化并使用命名空间。ZZO28资讯网——每日最新资讯28at.com

客户端服务端建立连接

第二步是建立连接。首先引入依赖。ZZO28资讯网——每日最新资讯28at.com

import io from "socket.io-client";

再进行实例化,得到一个 socket 实例。ZZO28资讯网——每日最新资讯28at.com

this.socket = io(process.env.VUE_APP_SOCKET_SERVER + "/chatroom");

有了这个 socket,我们就能监听各种事件了。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

聊天室的系统通知信息

当一个客户端连接上服务器时,服务器会发送一条消息,“hello,欢迎您加入在线聊天室!”这是通过单播实现的,只要拿着socket对象,调用其emit方法就行。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

除了对这个客户端打招呼外,还需要告诉其他用户,有新人加入了。这是通过socket.broadcast广播实现的。ZZO28资讯网——每日最新资讯28at.com

socket.broadcast.emit('broadcast', param);

当有人退出聊天室,会触发 disconnect 事件,此时我们可以广播通知其他人。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

这就是我们在前端页面看到的效果:ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

聊天对话功能

由于我们做的是聊天室,相当于一个群聊,就不涉及到单播聊天了,直接用广播就行。ZZO28资讯网——每日最新资讯28at.com

用户在客户端发聊天消息时,是用到socket对象的emit进行发送。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

这个chat事件是在客户端连接上服务端时开始监听的,在这个回调里,我们需要把内容广播给除发送者之外的其他用户,子事件名是new_chat_content。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

而其他用户则会通过客户端监听广播事件中的new_chat_content子事件拿到聊天数据,最终呈现到界面上。ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

图片图片ZZO28资讯网——每日最新资讯28at.com

以上都是通讯上的设计,了解了这个机制,UI 的展示就非常简单了,毕竟 UI = Render(data),不做更多介绍!ZZO28资讯网——每日最新资讯28at.com

小结

本文中,我首先分享了我对 WebSocket 协议的一些理解,希望对还不太理解这块的朋友起到一点帮助作用。面试里,WebSocket 是一个常问的考点,如果你回答的仅仅是“全双工通信”,可能并不能起到一个很好的效果,把文中小知识甩面试官脸上吧,哈哈哈!ZZO28资讯网——每日最新资讯28at.com

最终通过一个实际案例,带大家理解一个聊天室功能的设计思路,在实际落地的过程中夯实对 WebSocket 协议的理解。ZZO28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-92103-0.html别背八股文了,WebSocket 是什么,我劝你花几分钟让面试官惊艳!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: sync.WaitGroup和sync.Once的爱恨情仇

下一篇: Python 中 20 个鲜为人知的字符串函数

标签:
  • 热门焦点
  • 对标苹果的灵动岛 华为带来实况窗功能

    对标苹果的灵动岛 华为带来实况窗功能

    继苹果的灵动岛之后,华为也在今天正式推出了“实况窗”功能。据今天鸿蒙OS 4.0的现场演示显示,华为的实况窗可以更高效的展现出实时通知,比如锁屏上就能看到外卖、打车、银行
  • Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    Redmi Buds 4开箱简评:才199还有降噪 可以无脑入

    在上个月举办的Redmi Note11T Pro系列新机发布会上,除了两款手机新品之外,Redmi还带来了两款TWS真无线蓝牙耳机产品,Redmi Buds 4和Redmi Buds 4 Pro,此前我们在Redmi Note11T
  • JavaScript 混淆及反混淆代码工具

    JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • Rust中的高吞吐量流处理

    Rust中的高吞吐量流处理

    作者 | Noz编译 | 王瑞平本篇文章主要介绍了Rust中流处理的概念、方法和优化。作者不仅介绍了流处理的基本概念以及Rust中常用的流处理库,还使用这些库实现了一个流处理程序
  • 从零到英雄:高并发与性能优化的神奇之旅

    从零到英雄:高并发与性能优化的神奇之旅

    作者 | 波哥审校 | 重楼作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得
  • 当家的盒马,加速谋生

    当家的盒马,加速谋生

    来源 | 价值星球Planet作者 | 归去来自己“当家”的盒马,开始加速谋生了。据盒马官微消息,盒马计划今年开放生鲜供应链,将其生鲜商品送往食堂。目前,盒马在上海已经与
  • 2纳米决战2025

    2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
  • 微软发布Windows 11新版 引入全新任务栏状态

    微软发布Windows 11新版 引入全新任务栏状态

    近日,微软发布了Windows 11新版,而Build 22563更新主要引入了几周前曝光的平板模式任务栏等,系统更流畅了。更新中,Windows 11加入了专门针对平板优化的任务栏
  • Meta盲目扩张致超万人被裁,重金押注元宇宙而前景未明

    Meta盲目扩张致超万人被裁,重金押注元宇宙而前景未明

    图片来源:图虫创意日前,Meta创始人兼CEO 马克·扎克伯发布公开信,宣布Meta计划裁员超11000人,占其员工总数13%。他公开承认了自己的预判失误:“不仅
Top
Baidu
map