HTML5 WebSocket
WebSocket简介
WebSocket 是 HTML5 开始提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。
WebSocket 协议本质上是一个基于 TCP 的协议。
补充
TCP协议:TCP/IP是一种面向连接的、可靠的、基于字节流的传输层通信协议,它会保证数据不丢包、不乱序。它位于网络OSI模型中的第四层(传输层)。
每个TCP数据段都包含源端口和目的端口号,用于寻找发送端和接收端的应用进程。这两个值加上IP首部中的源端IP和目的端IP地址,有时候我们也会把它称为socket四元组(源IP地址、目的IP地址、源端口、目的端口)
工作流程
为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息 "Upgrade: WebSocket" 表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
补充:AJAX 轮询
在 WebSocket 诞生之前,要先实现服务端向客户端主动发送信息,很多情况下会使用 AJAX 轮询。
AJAX轮询:AJAX 轮询是指在特定的的时间间隔(如每1秒),由浏览器对服务器发出 HTTP 请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费带宽等资源。(网络带宽是指在单位时间(一般指的是1秒钟)内能传输的数据量)
- AJAX 轮询在一次请求和一次响应之后会断开 HTTP 连接,需要不停地连接才有可能实时获取消息;
- WebSocket 通信 则是建立持久的连接,客户端发送请求,服务器一旦有更新就会主动返回数据,非常适合用来做聊天室功能。
举个例子,对于聊天室功能,假如使用 AJAX 轮询 ,那么客户端A发送消息给客户端B,客户端B需要时时刻刻采用轮询的方式来询问服务端,是否有人发消息给我,有的话请推送给我;
如果采用 WebSocket 通信的形式,只要客户端A和B都与服务端建立起了 WebSocket 连接,这是一个长连接,客户端A想要发送消息给客户端B,那么A可以将请求发送至服务端,请求内容中包括要发送数据的客户端B的Id(可以在建立连接时就给每个客户端的 Websocket 实例绑定上用户的id),这样服务端一旦接收到请求,就可以遍历当前已与自己建立起连接的所有客户端,找到客户端B,并将消息推送给B。
两种方式对比,使用 WebSocket 能更好地节省服务器资源和带宽,也能够更实时地进行通讯。
WebSocket 的基本使用
- WebSocket 在浏览器端是 window 的一个内置对象,可以直接通过 new WebSocket 的形式创建一个实例。
- WebSocket 在服务端可以通过安装相对应的包来使用。
下面给出客户端使用案例
// 创建一个 WebSocket 实例,并指定连接的url,一般是服务端的ws接口
const socket = new WebSocket('ws://localhost:8080');
// 连接成功时触发open事件
socket.addEventListener('open', function (e) {
// 连接成功后可以使用 send 方法向服务端发送数据
socket.send({
id:B1,
msg:'我想跟你聊天'
});
});
// message事件可以收到服务端传输给客户端的数据,当有数据传输过来时,message事件触发
socket.addEventListener('message', function (e) {
console.log('e.data就是服务端推送过来的数据', e.data);
});
// 当一个连接被关闭时触发close事件
socket.addEventListener('close', function (e) {
});
服务端也有相对应的 API 来监听连接的状态,也同样有 send 方法来传输数据,message 方法接收数据。
心跳重连机制
websocket 在使用过程中,如果遭遇网络问题等,这个时候服务端没有触发 onclose 事件,这样会产生多余的连接,并且服务端会继续发送消息给客户端,造成数据丢失。 因此需要一种机制来检测客户端和服务端是否处于正常连接的状态,心跳检测和重连机制就产生了。
心跳重连机制指的是:使用定时器每隔一段时间,向服务器发送一个标记,服务器收到这个标记后再发送给客户端。在连接正常的情况下,客户端通过监听 message 事件可以获取到这个标记。 如果在这个指定时间内,客户端没有收到服务器端返回的标记,就判定连接断开了,使用 websocket.close 关闭连接。