WebTransport是为替代WebSockets而生?
大家好,很高兴又见面了,我是" 前端进阶 ",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
WebTransport能否替代WebSockets?前言
WebTransport 是一种新规范,使用 HTTP3 从服务器发送和接收数据的协议框架。 类似于 WebSockets,但支持多流、单向流、无序传输以及可靠/不可靠传输。目前Chrome、Edge、Opera浏览器已经支持WebTransport,火狐、Safari还未支持,具体如下图:
WebTransport的浏览器支持情况1.WebTransport成为WebSocket 替代方案?
WebSockets 是一种通过持久的单套接字socket在客户端和服务器之间实现全双工通信的技术,它允许低延迟、实时更新。
而较新的WebTransport有以下特性:可靠数据传输:发送方会收到数据传输成功或失败的通知,失败的传输通常会重新发送,直到成功为止,然后发送下一个数据包。不可靠传输:没有传输成功的确认,丢失数据包不会被重新传送。 这在注重传输速度、而非传输完整性的场景下可用,比如视频聊天。一个连接创建多个流:WebSockets 为每个连接创建一个流,而 WebTransport 可以在一个连接上创建多个流。 它避免了 WebSockets 所遭受的队头阻塞延迟,并且在创建连接时占用的资源较少。
WebSockets 以 HTTP/1.1 协议开始,但 WebTransport 可在多种不同的协议之上工作,包括一些 WebSockets 不支持的协议。HTTP/3 :HTTP/3 是万维网使用的传输协议的新版本。 HTTP/3 使用 QUIC 协议进行传输层数据交换,它有几个优点。 QUIC 可以防止队头阻塞延迟,在许多情况下提高网络性能。 这是 WebSockets 的限制。异步&Web Workers&多线程:通过 WebTransport,编码人员还可以使用 promises 和异步函数的 await 关键字等功能,同时API 也在 Web Workers 中运行,支持多线程。
下面是 WebTransport 工作组文档中的异步函数示例。const url = "https://example.com:4999/wt"; async function initTransport(url) { // 实例化WebTransport连接 const transport = new WebTransport(url); // The connection can be used once ready fulfills await transport.ready; } async function closeTransport(transport) { // 关闭连接 try { await transport.closed; console.log(`The HTTP/3 connection to ${url} closed gracefully.`); } catch(error) { console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`); } }2.WebTransport使用场景?2.1 加密流媒体
WebTransport 的流 API 允许您创建连接以发送有序数据。 由于 WebTransport 使用 QUIC 协议,与 TCP 相比,打开和关闭这些连接所需的资源更少。
您还可以做一些事情,例如更安全地提供流媒体。 WebTransport 有多种安全措施,例如要求使用 Origin 标头以及通过传输参数进行选择性加入。2.2 多人游戏
WebTransport 适用于 HTTP/2、HTTP/3 和 QUIC 协议。 它可以通过 HTTP 乱序接收数据,并且可以自己请求数据或监听服务器推送的数据。 它可以可靠地和不可靠地做到这一点。
通过WebTransport的双向流,服务器推送的数据延迟非常低,这对游戏开发来说是一个很大的优势。 它还可以缩短云游戏服务的响应时间。2.3 传感器数据
许多物联网 (IOT) 设备记录需要传输到服务器的数据,而 WebTransport 的潜在用途是使用低延迟方法来传输这些数据。 物联网设备经常定期发送少量数据, 消耗更少的资源对设备的电池寿命和网络拥塞都有好处。3. WebTransport 特性?
一起看看 WebTransport 提供了哪些具体特性和功能。 虽然该规范仍处于公开草案阶段,但已完全可用。除了 QUIC 协议之外,还有一个 API 可以让浏览器控制流和数据报。 API 仅支持 HTTPS,以加强安全性。3.1 QUIC
QUIC 是 Quick UDP Internet Connections 的缩写,谷歌发明的新传输协议。与 TCP 相比,QUIC 可以减少延迟。从表面上看,QUIC 非常类似于在 UDP 上实现的 TCP + TLS + HTTP/2。由于 TCP 是在操作系统内核和中间件固件 中实现的,因此对 TCP 进行重大更改几乎是不可能的。
但是,由于 QUIC 建立在 UDP 之上,因此没有这种限制。QUIC 可以实现可靠传输,而且相比于 TCP,它的 流控功能在用户空间而不在内核空间 ,那么使用者就不受限于 CUBIC 或是 BBR,而是可以自由选择,甚至根据应用场景自由调整优化。
QUIC 与现有 TCP + TLS + HTTP/2 方案相比,有以下几点特征: 利用缓存,显著减少连接建立时间 改善拥塞控制,拥塞控制从内核空间到用户空间 没有 head of line 阻塞的多路复用 前向纠错,减少重传 连接平滑迁移,网络状态的变更不会影响连接断线
Chrome 原生支持 QUIC,并且启用 QUIC 的服务器会一直支持 0-RTT 握手,在 Chrome 中可以通过如下命令打开 QUIC 配置: chrome://flags/ //浏览器直接访问
WebTransport 也可以在没有 QUIC 的情况下运行在 HTTP/2 或 HTTP/3 之上。 它还可以使用 HTTP/2 作为后备方案,让您可以利用 WebTransport 的优势,而无需考虑网络。3.2 数据报
WebTransport 主要处理数据报和流。 数据报是一个独立的数据包,可以以任何特定顺序到达。 数据报发送不可靠,如果某些数据丢失,连接也可以应付。 WebTransport 规范允许您使用"maxDatagramSize"属性限制数据报的大小。
maxDatagramSize的浏览器支持情况
WebTransport 对象有一个数据报对象,可以通过其可读和可写属性访问该对象。 数据报可以排队,您也可以创建promise等待数据报传输。
WebTransport 对象还包括状态数据,指示它们是正在连接、已连接、已关闭还是已失败。3.3 Stream
流允许您发送有序、可靠的数据。 您可以建立流并让服务器将此内容推送到客户端。 它允许低延迟、实时通信。
在 API 中,WebTransport 对象具有用于表示不同类型流的其他对象的插槽。 其中包括 SendStream、ReceiveStream 和 Bidirectional Stream 对象,目前这些还只存在于草案中。比如下面的Bidirectional Stream:async function setUpBidirectional() { const stream = await transport.createBidirectionalStream(); // stream is a WebTransportBidirectionalStream // stream.readable is a ReadableStream const readable = stream.readable; // stream.writable is a WritableStream const writable = stream.writable; }
使用流,您还可以将接收到的数据通过管道传输到处理程序中,例如 TextDecoderStream,它将数据转换为您的应用程序可以轻松使用的格式。3.4 发送流
SendStream 对象是一种用于传出数据的 WritableStream。 它们存储流对象,但 SendStream 对象还包含一个promise,它定义了它将采取的操作,例如关闭或中止。SendStream 对象还包含一个插槽,用于将它们附加到 HTTP/3 传输层。// 向服务器发送两个Uint8Array const stream = await transport.createSendStream(); const writer = stream.writable.getWriter(); const data1 = new Uint8Array([65, 66, 67]); const data2 = new Uint8Array([68, 69, 70]); writer.write(data1); writer.write(data2); try { await writer.close(); console.log("All data has been sent."); } catch (error) { console.error(`An error occurred: ${error}`); }3.5 接收流
ReceiveStream 对象是一种处理传入数据的 ReadableStream。ReceiveStream 对象的结构类似于 SendStream 对象,具有流槽和传输槽。 但是,它不包括promise。async function readFrom(receiveStream) { const reader = receiveStream.readable.getReader(); while (true) { const {done, value} = await reader.read(); if (done) { break; } // 值为 Uint8Array console.log(value); } } const rs = transport.receiveStreams(); const reader = rs.getReader(); while (true) { const {done, value} = await reader.read(); if (done) { break; } // 值为 ReceiveStream 的一个实例 await readFrom(value); }3.6 双向流
双向流将发送流和接收流组合到一个对象中,这使您可以在一个地方管理双向通信。 对象具有可读和可写的属性,对应于上面讨论的 ReceiveStream 和 SendStream 对象。
这些属性使它们能够处理双向发送的数据。 您读取传入流并写入传出流。3.7 单向流
您还可以创建单向流。 IncomingUnidirectionalStreams 是由多个 ReceiveStreams 组成的 ReadableStreams。 您可以调用 createUnidirectionalStream() 来创建传出等效项。async function writeData() { const stream = await transport.createUnidirectionalStream(); const writer = stream.writable.getWriter(); const data1 = new Uint8Array([65, 66, 67]); const data2 = new Uint8Array([68, 69, 70]); writer.write(data1); writer.write(data2); try { await writer.close(); console.log("All data has been sent."); } catch (error) { console.error(`An error occurred: ${error}`); } }4.WebTransport 可以取代 WebSockets 吗?
WebTransport 已经是 WebSockets 的可行替代品,没有线头阻塞、延迟稍低以及多协议方法的多功能性在许多场景中都有好处。
但是,由于WebTransport技术尚未完全敲定,开发工具较少,并且会持续一段时间。 现在预测 WebTransport 的用途还为时过早,但第一批使用它的团队完全有机会构建一些开创性的东西。
虽然没有迫切需要切换,但开发人员应该为未来的项目密切关注它,并准备好在最合适的情况下使用它。参考资料
https://ably.com/blog/can-webtransport-replace-websockets
https://blog.p2hp.com/archives/10031
about:blank