惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Troy Hunt's Blog
P
Proofpoint News Feed
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
K
Kaspersky official blog
Cyberwarzone
Cyberwarzone
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
S
Securelist
L
Lohrmann on Cybersecurity
Security Latest
Security Latest
T
Threatpost
H
Heimdal Security Blog
W
WeLiveSecurity
A
Arctic Wolf
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
IT之家
IT之家
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
TaoSecurity Blog
TaoSecurity Blog
A
About on SuperTechFans
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
N
News and Events Feed by Topic
Hacker News - Newest:
Hacker News - Newest: "LLM"
Last Week in AI
Last Week in AI
T
The Blog of Author Tim Ferriss
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
量子位
Stack Overflow Blog
Stack Overflow Blog
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
AI
AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
Vercel News
Vercel News
C
Cyber Attacks, Cyber Crime and Cyber Security
Latest news
Latest news
D
Darknet – Hacking Tools, Hacker News & Cyber Security
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security

博客园 - Zhentiw

[GenAI] Migration Plan: Flat API → Layered Architecture [Skill] Frontend Design Skill Claude Code Hooks: Complete Guide [GenAI] Pre-retieval overview [GenAI] About Indexing [GenAI] Indexing overview [Vibe Coding] 降低大模型幻觉 - 重试机制 [Vibe coding] 降低大模型幻觉 - JSON 安全输出提示词 [LangGraph] 应用结构 [LangGrpah] Unit testing [LangGraph] Functional API [LangGraph] 中断注意事项 [LangGraph] 中断相关细节 [LangGrpah] 静态断点 [LangGrpah] 非阻塞式中断 [LangGraph] 阻塞式中断 [LangGraph] 语义搜索 [LangGraph] 长期记忆 [LangGraph] 管理短期记忆 [LangGraph] 自定义checkpointer [LangGraph] 短期记忆 [LangGraph] 时间旅行 [LangGraph] checkpoint常用API [LangGraph] 元数据标记 [LangGraph] 流 [Vitest] mockClear, mockReset, mockRestore [LangGraph] 将子图添加为节点
[Node.js] WebSocket基础知识
Zhentiw · 2026-04-01 · via 博客园 - Zhentiw

实时场景的旧处理方案

考虑网页中的以下场景:

  • 股票K线图
  • 聊天
  • 警报、重要通知
  • 余座
  • 抢购页面的库存
  • ......

上述场景有一个共同特点——实时性

这种对实时性有要求的页面,会带来一些问题

比如下面的聊天场景

image-20250405132334026

由于HTTP协议是请求-响应模式,请求必须在前,响应必须在后,这就导致了服务器无法「主动」的把消息告诉客户端。

开发者想了很多办法来解决这一问题

当然终极解决方案自然是WebSocket,但了解过去的一些做法、参观前辈们经历的痛苦还是有益的。

短轮询

short polling,中文翻译为短轮询,是一种「话痨式」的方式。

客户端每隔一小段时间就向服务器请求一次,询问有没有新消息

sequenceDiagram 客户端->>服务器: 有新消息吗? 服务器->>客户端: 没 Note over 客户端,服务器: 一段时间后... 客户端->>服务器: 有新消息吗? 服务器->>客户端: 没 Note over 客户端,服务器: 一段时间后... 客户端->>服务器: 有新消息吗? 服务器->>客户端: 有,user1对你说:你好 Note over 客户端,服务器: 一段时间后... 客户端->>服务器: 有新消息吗? 服务器->>客户端: 没 Note over 客户端,服务器: 一段时间后... 客户端->>服务器: 有新消息吗? 服务器->>客户端: 没

实现短轮询是非常简单的,客户端只需要设置一个计时器不断发送请求即可

这种方案的缺陷是非常明显的:

  • 会产生大量无意义的请求
  • 会频繁打开关闭连接
  • 实时性并不高

长轮询

我们的前辈在有限的条件下,充分发挥智慧,来解决短轮询的问题,于是演化为长轮询

sequenceDiagram 客户端->>+服务器: 有新消息吗? Note right of 服务器: 没有消息不会响应 Note right of 服务器: 一段时间后... 服务器->>-客户端: user1对你说:你好 客户端->>+服务器: 有新消息吗? Note right of 服务器: 没有消息不会响应 Note right of 服务器: 一段时间后... 服务器->>-客户端: user1对你说:你吃了没 客户端->>服务器: ......

长轮询有效的解决了「话痨问题」,让每一次请求和响应都是有意义的

但长轮询仍然存在问题:

  • 客户端长时间收不到响应会导致超时,从而主动断开和服务器的连接

    这种情况是可以处理的,让ajax请求因为超时而结束时,立即重新发送请求到服务器

    虽然这种做法会让之前的请求变得无意义,但毕竟比短轮询好多了

  • 由于客户端可能「过早的」请求了服务器,服务器不得不挂起这个请求直到新消息的出现。这会让服务器长时间的占用资源却没什么实际的事情可做。

WebSocket

伴随着HTML5出现的WebSocket,从协议上赋予了服务器主动推送消息的能力

image-20250405134734354

从上图可以看出:

  • WebSocket也是建立在TCP协议之上的,利用的是TCP全双工通信的能力

    • 单工模式:数据的流向是单向的,不能反向,类似于收音机
    • 半双工:同一时候数据只能单向传输(要么是发送,要么是接收),类似于对讲机
    • 全双工:同一时候可以双向传输,类似于打电话
  • 使用WebSocket,会经历两个阶段:握手阶段、通信阶段

虽然优于轮询方案,但WebSocket仍然是有缺点的:

  • 兼容性

    WebSocket是HTML5新增的内容,因此古董版本的浏览器并不支持

  • 维持TCP连接需要耗费资源

    对于那些消息量少的场景,维持TCP连接确实会造成资源的浪费

原生API

https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket/WebSocket

const ws = new WebSocket("websocket服务器地址"); // 创建一个 websocket 连接

// 事件:
// 握手完成后会触发
ws.onopen = function(){}
// 收到服务器消息的时候会触发
ws.onmessage = function(){}
// 连接关闭之后会触发
ws.onclose = function(){}

// 方法:
ws.send(消息); // 向 websocket 服务器发送消息

// 属性:
ws.readyState // 连接状态 0-正在连接中 1-已连接 2-正在关闭中 3-已关闭

Socket.io

官网:https://socket.io/

原生的接口虽然简单,但是在实际应用中会造成很多麻烦

比如一个页面,既有K线,也有实时聊天,于是:

image-20250405133419271

上图是一段时间中服务器给客户端推送的数据,你能区分这些数据都是什么意思吗?

这就是问题所在:连接双方可以在任何时候发送任何类型的数据,另一方必须要清楚这个数据的含义是什么

回忆HTTP是如何处理这个问题的

你会如何解决这个问题

虽然我们可以自行解决这些问题,但毕竟麻烦

Socket.io 帮助我们解决了这些问题,它把消息放到不同的事件中,通过监听和触发事件来实现对不同消息的处理

image-20250405133335456

客户端和服务器双方事先约定好不同的事件(这些事件全部都是自定义事件),事件由谁监听,由谁触发,就可以把各种消息进行有序管理了。


-EOF-