WebSocket 和 HTTP 有什么区别?为什么需要 WebSocket?
WebSocket 是基于 TCP 的全双工通信协议,属于 HTML5 规范的一部分。与 HTTP 最大的区别在于通信模式:HTTP 是请求-响应模型,客户端发起请求后服务端才能返回数据,每次请求都携带完整头部(数百字节),连接完即断;WebSocket 通过 HTTP Upgrade 机制握手一次(客户端发送 Upgrade: websocket 头,服务端返回 101 Switching Protocols),之后在同一条 TCP 连接上双方可随时互发数据,头部开销仅 2-10 字节。这意味着服务端可以主动推送,延迟从 HTTP 轮询的数百毫秒降到毫秒级,适合聊天、实时行情、协同编辑、在线游戏等场景。WebSocket 连接是持久的,除非任一方发送关闭帧或网络中断,否则连接一直保持。
追问
WebSocket 握手为什么基于 HTTP?能不能跳过 HTTP 直接建立连接?
不能跳过。WebSocket 复用 HTTP 握手是为了兼容现有基础设施——浏览器先发一个标准 HTTP GET 请求(携带 Upgrade 头),中间的代理、负载均衡、防火墙都能识别并放行;如果直接用新协议,这些中间件会拒绝或破坏连接。握手成功后协议才切换为 WebSocket,之后的数据帧完全脱离 HTTP 格式。
HTTP/2 的 Server Push 能替代 WebSocket 吗?
不能。HTTP/2 Server Push 是服务端主动推送资源到浏览器缓存,本质还是服务于请求-响应模型,客户端无法通过 JavaScript 读取推送的原始内容;而且 Push 的资源受浏览器缓存策略控制,不适合实时数据流。WebSocket 是真正的双向消息通道,客户端可以用 JS 直接处理每一条推送消息。
WebSocket 连接断开时如何判断是网络问题还是服务端主动关闭?
WebSocket 关闭帧(Close Frame)携带状态码:1000 表示正常关闭,1001 表示端点离开,1006 表示异常关闭(没有收到关闭帧,通常是网络中断)。浏览器 onclose 事件的 code 和 reason 字段可以区分:code=1006 是网络问题需要重连,code=1000/1001 是正常关闭不需要重连。
大量 WebSocket 连接会压垮服务端吗?怎么控制?
会。每个 WebSocket 连接占用一个文件描述符和内存(约 10-50KB),单机默认 fd 上限通常 65535。控制手段:用 ulimit -n 或 systemd 调高 fd 上限;设最大连接数阈值超限拒绝;用 Redis Pub/Sub 做跨进程消息分发,单机只维护本机连接;横向扩展用 sticky session 或网关层路由,把同一用户的连接固定到同一后端。
javascript// WebSocket 握手过程示例 const ws = new WebSocket('wss://example.com/socket'); ws.onopen = () => { console.log('连接已建立,协议已升级'); ws.send('hello'); // 直接发送,无需 HTTP 请求 }; ws.onmessage = (event) => { console.log('收到服务端推送:', event.data); }; ws.onclose = (event) => { console.log('关闭码:', event.code, '原因:', event.reason); // code=1006 说明是异常断开,需要重连 };