WebTransport API
注意:此功能在 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 的基礎上包含額外資料。
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 向其寫入資料,以傳輸到伺服器。
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 的引用。您可以從中 獲取 writer,以允許將資料寫入流併發送到伺服器。
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 類,因此可以以相同的方式使用。
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() 來讀取它們。
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 屬性訪問它,該屬性返回一個包含 WebTransportBidirectionalStream 物件的 ReadableStream。每個物件都可以用於讀寫 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 |
瀏覽器相容性
載入中…