WebTransport API

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

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

WebTransport API 提供了一個對 WebSockets 的現代化更新,透過 HTTP/3 傳輸 在客戶端和伺服器之間傳輸資料。WebTransport 支援多路流、單向流和亂序傳輸。它透過 流 (streams) 實現可靠傳輸,並透過類 UDP 的資料報實現不可靠傳輸。

概念與用法

HTTP/3 自 2018 年以來一直在開發中。它基於 Google 的 QUIC 協議(該協議本身基於 UDP),並修復了經典 TCP 協議(HTTP 和 WebSockets 基於該協議)的幾個問題。

這些問題包括:

隊頭阻塞 (Head-of-line blocking)

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 變為 fulfilled,您就可以開始使用該連線了。

另請注意,您可以透過等待 WebTransport.closed Promise 變為 fulfilled 來響應連線關閉。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 物件,您可以使用 writer 向其寫入資料,以傳輸到伺服器。

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 的引用。您可以從中 獲取 writer,以允許將資料寫入流併發送到伺服器。

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 屬性訪問它,該屬性返回一個包含 WebTransportReceiveStream 物件的 ReadableStream。這些可以用於讀取伺服器傳送的 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 上可用的 reader 的引用,然後使用 reader 從伺服器讀取資料。每個塊都是一個 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 例項的引用。

注意: WebTransportBidirectionalStream 類似於 WebTransportDatagramDuplexStream,不同之處在於,在該介面中,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 屬性訪問它,該屬性返回一個包含 WebTransportBidirectionalStream 物件的 ReadableStream。每個物件都可以用於讀寫 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

瀏覽器相容性

另見