# 前置网络知识
从 TCP/IP 四层说起:
- 应用层:决定了如果向用户提供应用实时服务通信。HTTP、FTP、Websocket 都在这里。
- 传输层(TCP):负责数据的端到端传输。将应用层数据做报文分段,给每个报文添加端口、序号等数据,
- 网络层(IP):将 IP 地址映射到 MAC 地址,然后将 TCP 数据包加上 IP 相关信息后放到数据链路层来让其找到目标主机。
- 数据链路层:将数据包与电信号进行互相转换。
# Websocket
它和 HTTP 一样是应用层协议,并且也在传输层使用了 TCP 协议。一般可以通过 HTTP 的 101Upgrade 来升级为 Websocket 协议。
并且它支持双向通信,全双工通信。双方都可以随时发送、接收数据。
# Websocket 中的心跳检测
Websocket 是一个应用层协议,它本身有两种检测存活的方式。
- 一种是 TCP 底层的 KeepAlive 机制,一般是服务器端使用并且这个检测周期比较长,如果长期没有收到应答包才会通知应用层。
- 一种是自身协议实现的数据帧,有一个 ping-pong 数据帧,但是也只是服务器发送 ping 后客户端自动回复 pong 帧,在 JS 中不可控。
所以上面的方式都是服务器主动做心跳检测。浏览器是被动的,我们需要在浏览器端自己实现心跳检测。
# 什么情况下需要心跳检测
在浏览器端,关闭 Websocket 通常需要手动触发 onclose 回调函数。浏览器才会视作关闭了此次 Websocket 连接。
但是如果浏览器端意外断网或服务器意外关闭连接,没来得及触发 onclose 触发关闭帧,浏览器会长时间保持连接状态。此时业务代码如果不去主动检测,是无法感知的。
所以我们要做的就是尽量保证这个连接是存活的,如果不正常需要主动的去做优化(比如重新连接)。
# 怎么做
客户端可以定时放心跳包,并用 status 存储状态。有三种状态:
- 等待应答。
- 收到应答。
- 超时。
然后我们可以根据状态来判断是否需要重连以及在应用层给予用户提示。