WebSocket 入门:从 HTTP 轮询到实时双向通信

举报
yd_85202127 发表于 2026/11/15 06:28:54 2026/11/15
【摘要】 一、HTTP 的“问一句答一句”够用吗?打开网页、刷短视频、查天气,这些场景都有一个共同点:客户端先发起请求,服务端再返回响应,HTTP 的“一问一答”模型完全够用。但当需求变成“服务器有新消息要第一时间推给我”时,这个模型就显得笨拙了。聊天消息、股票行情、在线文档协同编辑、多人游戏状态同步,都要求服务端能主动把数据推到浏览器,而不是等浏览器来问。 二、轮询:最直观却最浪费的办法最容易想到...

一、HTTP 的“问一句答一句”够用吗?

打开网页、刷短视频、查天气,这些场景都有一个共同点:客户端先发起请求,服务端再返回响应,HTTP 的“一问一答”模型完全够用。但当需求变成“服务器有新消息要第一时间推给我”时,这个模型就显得笨拙了。聊天消息、股票行情、在线文档协同编辑、多人游戏状态同步,都要求服务端能主动把数据推到浏览器,而不是等浏览器来问。

二、轮询:最直观却最浪费的办法

最容易想到的办法是轮询:浏览器每隔几秒发一次请求问“有新消息吗”。它实现简单、兼容性好,但代价明显:大多数请求得到的回答都是“没有”,白白消耗了带宽和服务器算力;间隔设得太长,消息延迟大,设得太短,空请求更多。长轮询做了改进:服务端先把请求挂起,有数据了再返回,客户端收到后立刻再发一个请求。这样空转少了,但每次有数据都要重建连接,服务端还要同时挂起大量连接,内存和线程压力并不小。

三、WebSocket:一次握手,长期在线

WebSocket 在 2011 年成为 RFC 6455 标准,它的思路是:先用一次普通的 HTTP 请求完成“握手升级”,之后这条 TCP 连接就不再走 HTTP 报文,而是一直保持打开,双方随时可以互相发送数据帧。这就是全双工通信:客户端能发,服务端也能主动推,不用再等对方来问。

握手的关键在两个请求头。客户端发出的请求里带有 Upgrade: websocket 和一个随机生成的 Sec-WebSocket-Key;服务端校验通过后返回 101 Switching Protocols,并把这个 Key 加上一个固定的 GUID 字符串做 SHA-1 再 Base64 编码,放进 Sec-WebSocket-Accept 返回。浏览器拿到后一验算,就知道对方确实是按 WebSocket 协议应答的,连接随即升级成功。

四、数据是怎么传的:帧

升级之后,数据以“帧”为单位传输。帧很轻量:一个文本帧只有几字节的头部开销,远小于每次 HTTP 请求动辄几百字节的请求头。浏览器内置的 WebSocket API 用起来也很直接:

const ws = new WebSocket('wss://example.com/chat');
ws.onopen = () => ws.send('你好');
ws.onmessage = (event) => console.log('收到:', event.data);
ws.onclose = () => console.log('连接已关闭');

服务端同样简单,以 Node.js 的 ws 库为例,几行代码就能接受连接并广播消息。帧还分文本帧和二进制帧,心跳用 ping 和 pong 帧维持,关闭时双方互发关闭帧体面告别。还有一个细节:浏览器发出的帧必须经过掩码处理,这是协议用来防止缓存投毒攻击的设计。

五、用到生产环境,还要补上这几课

第一,用 wss 而不是 ws。wss 跑在 TLS 之上,能防止中间人窃听和篡改,也能穿过大多数代理和防火墙。第二,反向代理要透传升级头,Nginx 需要显式配置 Upgrade 和 Connection 头,否则握手会在代理层被挡住。第三,心跳与重连缺一不可:网络抖动、代理超时都可能悄悄断开连接,客户端要定时发 ping 检测存活,断开后按指数退避重连,而不是无脑死循环。第四,鉴权要在握手时做完,常见做法是握手请求携带已登录的 Cookie,或在建连前先用 HTTP 接口换取一次性票据,不要把长期有效的令牌直接写在 URL 里,因为它会被记进访问日志。第五,服务要扩到多台机器时,单机内存里的连接表就不够用了,通常用 Redis 的发布订阅把消息同步到各节点,再由持有连接的节点推送给客户端。最后别忘了限流:单个连接发送消息的频率也要有上限,避免被恶意客户端拖垮。

六、小结

HTTP 的请求响应模型适合“你问我答”的场景;一旦需要服务端主动推送、双向实时交互,WebSocket 就是更合适的工具。它并不神秘:一次 HTTP 升级握手,换来一条长期可用的全双工通道,剩下的工作是把心跳、重连、鉴权和扩容这些生产细节补齐。理解了这一层,再去看聊天室、实时看板、协同文档这些产品,底层的通信思路就都通了。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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