WebSocket 是一种在客户端和服务器之间建立双向通信的技术。既然是双向的,WebSocket 就可以用于聊天室、实时协作等场景。在 ECMAScript 2019 中,我们看到了增强型协议(Improvements to the WebSocket Protocol),它提供了更好的性能和可靠性,下面我们来看看这个新特性。
WebSocket 简介
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通信的协议。基于 WebSocket 协议,浏览器和服务器可以进行全双工通信,实现了真正的实时性。不同于 Ajax 轮询和 Comet 长轮训的方式,WebSocket 采用了握手协议,建立起连接之后,建立了一个持久化的连接,并通过心跳包来保持连接。
下面是一个 WebSocket 连接示例:
// javascriptcn.com 代码示例 const socket = new WebSocket('ws://localhost:8080'); socket.onopen = function() { console.log('WebSocket 连接已建立'); } socket.onmessage = function(event) { console.log('接收到消息:' + event.data); } socket.onclose = function(event) { if (event.wasClean) { console.log('WebSocket 连接已正常关闭'); } else { console.log('WebSocket 连接异常断开'); } } socket.onerror = function(event) { console.log('WebSocket连接发生错误'); }
当 WebSocket 连接建立后,onopen 回调函数会被触发,表示连接已建立。当服务器端发送消息时,onmessage 回调函数会被触发,传入的 event 参数就是消息内容。当 WebSocket 连接主动断开或被动断开时,onclose 回调函数会被触发。当 WebSocket 连接发生错误时,onerror 回调函数会被触发。
以上就是关于 WebSocket 的基本介绍,下面我们来看看 ECMAScript 2019 中提供的增强型协议。
增强型协议
在 ECMAScript 2019 中,WebSocket 的协议进行了增强,提供了更好的性能和可靠性。主要增加了以下特性:
二进制数据发送与接收
在 ECMAScript 2019 之前,WebSocket 的数据传输都是纯文本格式。现在,我们可以使用 ArrayBuffer 和 Blob 等二进制格式进行数据的发送与接收。下面是发送二进制数据的示例:
// javascriptcn.com 代码示例 const arrayBuffer = new ArrayBuffer(16); const view = new DataView(arrayBuffer); view.setUint32(0, 100); view.setUint32(4, 200); view.setFloat32(8, 300.5); view.setFloat32(12, 400.5); const socket = new WebSocket('ws://localhost:8080'); socket.onopen = function() { socket.send(arrayBuffer); }
在这个示例中,我们先创建了一个 16 字节的 ArrayBuffer,然后使用 DataView 对其进行操作。最后,我们使用 socket.send() 方法将数组缓存发送到服务器端。
在服务器端接收到这个数据包后,我们可以使用如下代码解析它:
// javascriptcn.com 代码示例 const arrayBuffer = new ArrayBuffer(16); const view = new DataView(arrayBuffer); socket.on('message', function(message) { view.setInt32(0, message.readUInt32BE(0)); view.setInt32(4, message.readUInt32BE(4)); view.setFloat32(8, message.readFloatBE(8)); view.setFloat32(12, message.readFloatBE(12)); });
使用 readUInt32BE() 和 readFloatBE() 方法对二进制数据进行解析,然后再使用 DataView 对其进行包装。
WebSocket 错误代码
在 ECMAScript 2019 中,WebSocket 新增了错误代码,具体如下:
- 1006:连接关闭且无法读取数据(一般出现在 ping/pong 异常时)
- 1011:服务器端无法处理请求,可能是由于协议版本不兼容或请求格式不正确造成的
- 1012:服务器重启或关闭导致的 WebSocket 连接断开
- 1013:WebSocket server 收到了超过它能处理的数据,导致连接断开
- 1015:TLS 握手失败(该错误是一个保留错误码,不能作为普通错误处理)
在上述代码中,如果错误码不为 1000,需要进行额外的错误处理。特别是当错误码为 1006 时,表示连接关闭且无法读取数据,可能是因为 ping/pong 异常,因此我们需要进行 ping/pong 维护,可以使用 WebSocket 的 heartbeats 库来解决这个问题。
心跳包维护
在 ECMAScript 2019 中,WebSocket 增加了对心跳包的支持。心跳包可以用于维护连接状态,防止连接因为长时间不活动而被关闭。
下面是心跳包的示例代码:
// javascriptcn.com 代码示例 const socket = new WebSocket('ws://localhost:8080'); let heartbeatInterval = null; socket.onopen = function() { heartbeatInterval = setInterval(function() { socket.send('ping'); }, 30000); } socket.onmessage = function(event) { if (event.data === 'pong') { // 接收到 pong,什么也不做 } } socket.onclose = function() { clearInterval(heartbeatInterval); }
在这个示例代码中,我们使用 setInterval() 方法定时发送 ping 包,接收到 pong 包后,什么也不做。当 WebSocket 连接断开时,我们需要清除掉定时器。
总结
ECMAScript 2019 的增强型 WebSocket 协议提供了更好的性能和可靠性。在新的协议中,我们可以使用 ArrayBuffer 和 Blob 等二进制格式进行数据传输,同时还增加了 WebSocket 错误代码和心跳包维护。无论是在开发聊天室、实时协作等场景下,都可以使用 WebSocket 技术来提升应用的实时性和性能表现。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652df3257d4982a6ebf0a1b3