WebTransport API

有限可用性

此功能不是基线,因为它在一些最常用的浏览器中无法使用。

安全上下文:此功能仅在 安全上下文 (HTTPS) 中可用,在某些或所有 支持的浏览器 中可用。

注意:此功能在 Web Workers 中可用。

WebTransport APIWebSockets 提供了现代更新,使用 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 集之外,还包含其他数据。

js
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 对象,您可以使用写入器向其写入数据,以将数据传输到服务器

js
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 对象,您可以使用它从服务器接收数据

js
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 的引用。从这里,您可以 获取一个写入器 以允许将数据写入流并发送到服务器。

js
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 类,因此可以使用相同的方式

js
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() 来读取它们

js
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 的引用。它包含 readablewritable 属性,它们返回对 WebTransportReceiveStreamWebTransportSendStream 实例的引用,这些实例可用于从服务器读取数据和写入服务器数据。

注意:WebTransportBidirectionalStreamWebTransportDatagramDuplexStream 类似,只是在该接口中,readablewritable 属性分别是 ReadableStreamWritableStream

js
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 读取数据

js
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 写入数据

js
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 实例,如上所示。但是,与单向示例一样,您首先需要一个初始函数来读取双向流

js
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 表格仅在浏览器中加载

另请参阅