在 HTTP协议中,客户端必须先发起请求,服务器才能响应。这就像发邮件,你发一封,对方回一封。但如果需要开发一个即时聊天室、股票大盘或者实时视频监控的功能,让客户端每隔几秒钟问一次服务器“有新消息吗?”(轮询),既浪费带宽,延迟又高。WebSocket是解决这个问题的最优解。
一、 什么是 WebSocket?
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
- HTTP: 单向传输。只能由客户端发起,服务端响应。
- WebSocket: 双向传输。建立连接后,服务器和客户端可以随时向对方发送数据。
它的最大优点是:建立连接后,数据传输不仅实时,而且头部开销极小(不再需要像 HTTP 那样每次都带上一大堆 Header)。
二、 它是如何工作的?
WebSocket 并不是凭空建立的,它借用了 HTTP 来“搭桥”。
- 发起请求:客户端发送一个标准的 HTTP GET 请求,但在 Header 里带上
Upgrade: websocket,告诉服务器:“我想把协议升级为 WebSocket”。 - 协议切换:服务器如果支持,会返回
101 Switching Protocols状态码。 - 通道建立:此时,HTTP 连接中断,底层的 TCP 连接保持打开,双方开始使用 WebSocket 的二进制帧格式传输数据。
三、 生产环境中的痛点:连接“假死”
在本地开发(localhost)时,WebSocket 看起来非常稳定。但在真实的公网环境中,情况要复杂得多:
- 网络波动:手机进入电梯、WiFi 切换 4G,连接随时可能断开。
- 僵尸连接(Half-Open):有时候网线被拔掉,或者中间的路由器为了节省资源默默切断了连接,但客户端和服务器都不知道,双方还以为连接连着,结果发消息谁也收不到。
为了解决这个问题,我们需要引入心跳检测(Heartbeat)和断线重连机制。
心跳检测:定期向服务器发送Ping,接收服务器传回来的Pong,如果没有在规定时间内返回,就认为连接已经断开
四、 封装一个带有心跳检测和短线重连的 WebSocket 类
- 定期发送 Ping:证明我还活着。
- 倒计时等待 Pong:如果发了 Ping 之后 3 秒内没收到回复,判定连接已断,主动关闭。
- 自动重连:连接断开后,延迟几秒尝试重新连接。
1 | class WebSocketManager { |