WebSocket 入门:从一次握手看懂长连接

举报
yd_213156404 发表于 2026/11/12 00:45:06 2026/11/12
【摘要】 聊天消息、股票行情、协同编辑——很多场景都需要服务器主动把数据推给浏览器。HTTP 是“客户端先问、服务端再答”的请求-响应模型,要实现实时推送,只能靠反复轮询或长轮询,既浪费带宽,延迟也高。WebSocket 就是为解决这个问题而生的:一次握手,建立一条全双工的长连接,此后双方可以随时互相发送消息。 一次看似普通的 HTTP 握手WebSocket 的握手借用了 HTTP。浏览器先发出一个...

聊天消息、股票行情、协同编辑——很多场景都需要服务器主动把数据推给浏览器。HTTP 是“客户端先问、服务端再答”的请求-响应模型,要实现实时推送,只能靠反复轮询或长轮询,既浪费带宽,延迟也高。WebSocket 就是为解决这个问题而生的:一次握手,建立一条全双工的长连接,此后双方可以随时互相发送消息。

一次看似普通的 HTTP 握手

WebSocket 的握手借用了 HTTP。浏览器先发出一个普通的 HTTP 请求,但带上两个关键头:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

Upgrade: websocket 是在告诉服务器:“我想把这条连接升级成 WebSocket”。服务器同意后返回 101 状态码:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Sec-WebSocket-Accept 是服务器把客户端的 Key 加上一段固定字符串后做 SHA-1 再 Base64 得出的,用来证明服务器确实理解 WebSocket 协议。握手完成后,HTTP 就退场了,同一条 TCP 连接转而传输 WebSocket 帧。

帧:长连接上的最小单位

握手之后传输的不再是 HTTP 报文,而是一帧一帧的消息。每帧都有简短的头部:操作码说明它是文本、二进制、关闭还是心跳(Ping/Pong),长度字段控制着载荷大小,一个大消息可以拆成多帧连续发送。Ping/Pong 帧用来探测对方是否还活着,中间的代理和负载均衡器也靠它判断连接是否空闲。

理解“帧”能帮你避开一个常见误区:应用层按帧解析即可,半包、粘包是 TCP 层面的现象,乱序和丢失由 TCP 负责,应用程序不用操心。

为什么不是一直用它

长连接也有代价。服务器要为每个连接维持状态,内存和文件描述符都会随在线用户数增长;连接断开后还要处理重连、断线重发和消息去重。聊天室和行情推送这类“服务端主动推、消息频繁”的场景值得付出这个代价;而偶尔查一次的数据,用普通 HTTP 反而更简单、更省资源。

一个实用的判断方法是:数据是不是“不知道什么时候会来”?如果是,就用 WebSocket;如果客户端知道自己什么时候需要数据,就用 HTTP。常见的折中做法是:用 HTTP 做登录和拉取历史记录,用 WebSocket 只做实时增量推送。

写一段最简单的客户端

浏览器原生就支持 WebSocket,不用任何库:

const ws = new WebSocket("wss://example.com/chat");
ws.onopen = () => ws.send(JSON.stringify({ type: "hello", name: "Tom" }));
ws.onmessage = (e) => console.log("收到:", e.data);
ws.onclose = () => console.log("连接已关闭,稍后重连");

注意两点:生产环境一律用 wss://(TLS 加密),不要用明文 ws://;onclose 里要安排重连——网络波动、服务器重启、代理超时都会悄悄断开连接,一个带退避间隔的重连循环,比“假设连接永远不断”可靠得多。

小结

WebSocket 的本质可以用三句话概括:用一次 HTTP 握手换来一条长期可用的 TCP 连接;连接之上的通信单位是帧;它适合服务端主动推送的场景,但不适合所有场景。下次看到实时聊天或行情页面时,不妨打开浏览器开发者工具的 Network 面板,找找那条返回 101 的请求——那就是长连接诞生的瞬间。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。