WebTransport API
注意:此功能在 Web Workers 中可用。
WebTransport API 为 WebSockets 提供了现代更新,使用 HTTP/3 传输 在客户端和服务器之间传输数据。WebTransport 支持多路流、单向流和无序交付。它通过 流 实现可靠传输,通过类 UDP 数据报实现不可靠传输。
概念和用法
HTTP/3 自 2018 年以来一直在开发中。它基于 Google 的 QUIC 协议(本身基于 UDP),并修复了围绕经典 TCP 协议(HTTP 和 WebSockets 基于该协议)的几个问题。
这些问题包括
- 首行阻塞
-
HTTP/2 允许多路复用,因此单个连接可以同时流式传输多个资源。但是,如果单个资源失败,则该连接上的所有其他资源将被阻塞,直到任何丢失的数据包被重新传输。使用 QUIC,只有失败的资源受到影响。
- 更快的性能
-
QUIC 在许多方面都比 TCP 性能更高。QUIC 可以自行处理安全功能,而不是将责任委托给其他协议(如 TLS)——这意味着更少的往返次数。并且流比旧的包机制提供了更好的传输效率。这会产生重大影响,尤其是在高延迟网络上。
- 更好的网络转换
-
QUIC 使用唯一的连接 ID 来处理每个请求的源和目标——以确保数据包能够正确交付。此 ID 可以在不同的网络之间持久化,这意味着,例如,如果您从 Wi-Fi 切换到移动网络,下载可以继续而不会中断。另一方面,HTTP/2 使用 IP 地址作为标识符,因此网络转换可能会出现问题。
- 不可靠传输
-
HTTP/3 通过数据报支持不可靠的数据传输。
WebTransport API 为通过 HTTP/3 进行双向通信提供了低级访问,利用了上述优势,并支持可靠和不可靠的数据传输。
初始连接
要打开与 HTTP/3 服务器的连接,请将服务器的 URL 传递给 WebTransport()
构造函数。请注意,方案需要是 HTTPS,并且需要显式指定端口号。一旦 WebTransport.ready
Promise 履行,您就可以开始使用连接。
另请注意,您可以通过等待 WebTransport.closed
Promise 履行来响应连接关闭。WebTransport 操作返回的错误类型为 WebTransportError
,并且除了标准 DOMException
集之外,还包含其他数据。
const url = "https://example.com:4999/wt";
async function initTransport(url) {
// Initialize transport connection
const transport = new WebTransport(url);
// The connection can be used once ready fulfills
await transport.ready;
// ...
}
// ...
async function closeTransport(transport) {
// Respond to connection closing
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}.`);
}
}
通过数据报进行不可靠传输
“不可靠”意味着数据传输没有保证,也不能保证按特定顺序到达。在某些情况下这是可以的,并且提供了非常快的交付速度。例如,您可能希望传输定期游戏状态更新,其中每条消息都取代最后到达的消息,并且顺序并不重要。
不可靠数据传输通过 WebTransport.datagrams
属性处理——它返回一个 WebTransportDatagramDuplexStream
对象,其中包含您向服务器发送数据报和接收数据报所需的一切。
WebTransportDatagramDuplexStream.writable
属性返回一个 WritableStream
对象,您可以使用写入器向其写入数据,以将数据传输到服务器
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
WebTransportDatagramDuplexStream.readable
属性返回一个 ReadableStream
对象,您可以使用它从服务器接收数据
async function readData() {
const reader = transport.datagrams.readable.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
// value is a Uint8Array.
console.log(value);
}
}
通过流进行可靠传输
“可靠”意味着数据传输和顺序得到保证。这提供了较慢的交付速度(尽管比 WebSockets 快),并且在可靠性和排序很重要的情况下需要(例如,聊天应用程序)。
在使用通过流进行可靠传输时,您还可以设置同一传输上不同流的相对优先级。
单向传输
要从用户代理打开单向流,请使用 WebTransport.createUnidirectionalStream()
方法获取对 WritableStream
的引用。从这里,您可以 获取一个写入器 以允许将数据写入流并发送到服务器。
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}`);
}
}
另请注意使用 WritableStreamDefaultWriter.close()
方法在所有数据发送完毕后关闭关联的 HTTP/3 连接。
如果服务器打开单向流以将数据传输到客户端,则可以通过 WebTransport.incomingUnidirectionalStreams
属性在客户端访问它,该属性返回一个 ReadableStream
,其中包含 WebTransportReceiveStream
对象。这些对象可用于读取服务器发送的 Uint8Array
实例。
在这种情况下,首先要做的是设置一个函数来读取 WebTransportReceiveStream
。这些对象继承自 ReadableStream
类,因此可以使用相同的方式
async function readData(receiveStream) {
const reader = receiveStream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
// value is a Uint8Array
console.log(value);
}
}
接下来,调用 WebTransport.incomingUnidirectionalStreams
并获取对它返回的 ReadableStream
上可用的阅读器的引用,然后使用阅读器从服务器读取数据。每个块都是一个 WebTransportReceiveStream
,我们使用之前设置的 readFrom()
来读取它们
async function receiveUnidirectional() {
const uds = transport.incomingUnidirectionalStreams;
const reader = uds.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
// value is an instance of WebTransportReceiveStream
await readData(value);
}
}
双向传输
要从用户代理打开双向流,请使用 WebTransport.createBidirectionalStream()
方法获取对 WebTransportBidirectionalStream
的引用。它包含 readable
和 writable
属性,它们返回对 WebTransportReceiveStream
和 WebTransportSendStream
实例的引用,这些实例可用于从服务器读取数据和写入服务器数据。
注意:WebTransportBidirectionalStream
与 WebTransportDatagramDuplexStream
类似,只是在该接口中,readable
和 writable
属性分别是 ReadableStream
和 WritableStream
。
async function setUpBidirectional() {
const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a WebTransportReceiveStream
const readable = stream.readable;
// stream.writable is a WebTransportSendStream
const writable = stream.writable;
...
}
然后,可以按如下方式从 WebTransportReceiveStream
读取数据
async function readData(readable) {
const reader = readable.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
// value is a Uint8Array.
console.log(value);
}
}
并且可以按如下方式向 WebTransportSendStream
写入数据
async function writeData(writable) {
const writer = writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
}
如果服务器打开双向流以将数据传输到客户端并从客户端接收数据,则可以通过 WebTransport.incomingBidirectionalStreams
属性访问它,该属性返回一个 ReadableStream
,其中包含 WebTransportBidirectionalStream
对象。每个对象都可用于读取和写入 Uint8Array
实例,如上所示。但是,与单向示例一样,您首先需要一个初始函数来读取双向流
async function receiveBidirectional() {
const bds = transport.incomingBidirectionalStreams;
const reader = bds.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
// value is an instance of WebTransportBidirectionalStream
await readData(value.readable);
await writeData(value.writable);
}
}
接口
WebTransport
-
提供功能以使用户代理能够连接到 HTTP/3 服务器,在任何一个或两个方向启动可靠和不可靠的传输,并在不再需要连接时关闭连接。
WebTransportBidirectionalStream
-
表示服务器或客户端创建的双向流,可用于可靠传输。提供对用于读取传入数据的
ReadableStream
和用于写入传出数据的WritableStream
的访问。 WebTransportDatagramDuplexStream
-
表示可用于在客户端和服务器之间进行数据报不可靠传输的双工流。提供对用于读取传入数据报的
ReadableStream
、用于写入传出数据报的WritableStream
以及与流相关的各种设置和统计信息的访问。 WebTransportError
-
表示与 WebTransport API 相关的错误,这些错误可能是由于服务器错误、网络连接问题或客户端发起的中止操作(例如,由于
WritableStream.abort()
调用)引起的。 WebTransportReceiveStream
-
为传入的 WebTransport 单向或双向
WebTransport
流提供流式功能。 WebTransportSendStream
-
为传出的 WebTransport 单向或双向
WebTransport
流提供流式功能。
示例
规范
规范 |
---|
WebTransport # web-transport |
浏览器兼容性
BCD 表格仅在浏览器中加载