Korzystanie z WebTransport

WebTransport to interfejs API oferujący małe opóźnienia, dwukierunkową komunikację klient-serwer. Dowiedz się więcej o jego zastosowaniach i o tym, jak poinformować nas o jego przyszłości.

Wprowadzenie

Co to jest WebTransport?

WebTransport to internetowy interfejs API, który korzysta z protokołu HTTP/3 jako transportu dwukierunkowego. Umożliwia dwukierunkową komunikację między klientem internetowym a serwerem HTTP/3. Obsługuje niepewne wysyłanie danych zarówno przez interfejsy API datagramów, jak i niezawodnie przez interfejsy API strumieni danych.

Datagramy idealnie nadają się do wysyłania i odbierania danych, które nie wymagają silnych gwarancji dostarczenia. Pojedyncze pakiety danych są ograniczone przez maksymalną jednostkę przesyłania (MTU) bazowego połączenia i mogą – ale nie muszą – być prawidłowo przesyłane, a jeśli są przesyłane, mogą być dostarczane w dowolnej kolejności. Dzięki tym cechom interfejsy API datagramów idealnie nadają się do przesyłania danych z małym opóźnieniem i z możliwością jak najlepszych. Możesz traktować datagramy jak wiadomości protokołu danych użytkownika (UDP), ale zaszyfrowane i kontrolowane przez przeciążenia.

Interfejsy API strumieni zapewniają natomiast niezawodne uporządkowane przesyłanie danych. Są dobrze sprawdzają się w sytuacjach, w których musisz wysyłać lub odbierać co najmniej 1 strumienie uporządkowanych danych. Używanie wielu strumieni WebTransport jest analogiczne do tworzenia wielu połączeń TCP, ale ponieważ HTTP/3 korzysta z lżejszego protokołu QUIC, można je otwierać i zamykać bez dodatkowego nakładu pracy.

Przykłady zastosowań

Oto krótka lista możliwych sposobów korzystania przez deweloperów z WebTransport.

  • Wysyłanie stanu gry w regularnych odstępach czasu z minimalnym czasem oczekiwania na serwer za pomocą małych, niestabilnych wiadomości w złej kolejności.
  • Odbieranie strumieni multimedialnych przesyłanych z serwera z minimalnym opóźnieniem, niezależnie od innych strumieni danych.
  • Otrzymywanie powiadomień przesyłanych z serwera, gdy otwarta jest strona internetowa.

Chcemy dowiedzieć się więcej o tym, w jaki sposób zamierzasz korzystać z WebTransport.

Obsługiwane przeglądarki

Obsługa przeglądarek

  • 97
  • 97
  • 114
  • x

Źródło

Podobnie jak w przypadku wszystkich funkcji, które nie mają uniwersalnej obsługi przeglądarek, sprawdzoną metodą jest kodowanie defensywne z wykorzystaniem wykrywania funkcji.

Obecny stan,

Step Stan
1. Utwórz wyjaśnienie Zakończono
2. Utwórz wstępną wersję roboczą specyfikacji Zakończono
3. Zbieraj opinie i ulepszaj projekt Odpowiedź była wyczerpująca
4. Testowanie origin Odpowiedź była wyczerpująca
5. Uruchomienie kampanii Chromium 97

Związek WebTransport z innymi technologiami

Czy protokół WebTransport zastąpi protokół WebSockets?

Być może. W niektórych przypadkach prawidłowymi protokołami komunikacyjnymi mogą być protokoły WebSockets lub WebTransport.

Komunikacja WebSockets opiera się na pojedynczym, niezawodnym i uporządkowanym strumieniu wiadomości, co jest odpowiednie w przypadku niektórych rodzajów potrzeb komunikacji. Jeśli potrzebujesz tych cech, mogą je zapewnić również interfejsy API strumieniowania WebTransport. Interfejsy API datagramu stosowane w WebTransport API zapewniają natomiast dostarczanie z małym opóźnieniem, bez gwarancji niezawodności i zamówienia. Nie zastępują więc rozwiązania WebSockets.

Dzięki korzystaniu z WebTransport przez interfejsy API datagram lub wiele równoczesnych instancji Streams API nie musisz się martwić o blokowanie z góry strony, które może być przyczyną problemów z WebSockets. Ponadto nawiązywanie nowych połączeń zwiększa wydajność, ponieważ uzgadnianie połączenia QUIC trwa krócej niż uruchamianie TCP przez TLS.

WebTransport wchodzi w skład nowej specyfikacji roboczej, dlatego ekosystem WebSocket wokół bibliotek klienta i serwera jest obecnie znacznie bardziej rozbudowany. Jeśli potrzebujesz gotowego rozwiązania, które będzie działać „od razu” przy typowych konfiguracjach serwerów i w przypadku szerokiej obsługi klientów internetowych, WebSockets jest obecnie lepszym rozwiązaniem.

Czy interfejs WebTransport to to samo co interfejs UDP Socket API?

Nie. WebTransport nie jest UDP Socket API. WebTransport wykorzystuje protokół HTTP/3, który z kolei używa „wewnętrznych” protokołu UDP, jednak WebTransport ma wymagania dotyczące szyfrowania i kontroli przeciążenia, co sprawia, że jest to coś więcej niż podstawowy interfejs UDP Socket API.

Czy WebTransport to alternatywa dla kanałów danych WebRTC?

Tak, w przypadku połączeń klient-serwer. WebTransport ma wiele tych samych właściwości co kanały danych WebRTC, ale ich podstawowe protokoły są różne.

Ogólnie rzecz biorąc, obsługa serwera zgodnego z HTTP/3 wymaga mniej konfiguracji niż utrzymanie serwera WebRTC, co wymaga zrozumienia wielu protokołów (ICE, DTLS i SCTP) w celu uzyskania sprawnego transportu. WebRTC wiążą się z nimi wiele innych elementów, które mogą prowadzić do nieudanych negocjacji klienta/serwera.

Interfejs WebTransport API został zaprojektowany z myślą o przypadkach użycia przeznaczonych dla programistów internetowych i powinien przypominać pisanie kodu na nowoczesnej platformie internetowej niż korzystanie z interfejsów kanałów danych WebRTC. W przeciwieństwie do WebRTC interfejs WebTransport jest obsługiwany w procesach Web Workers, co pozwala na realizację komunikacji klient-serwer niezależnie od danej strony HTML. WebTransport udostępnia interfejs zgodny ze strumieniami, więc obsługuje optymalizacje związane z obciążeniem wstecznym.

Jeśli jednak masz już działającą konfigurację klienta/serwera WebRTC, przejście na WebTransport może nie dawać zbyt wielu korzyści.

Wypróbuj

Najlepszym sposobem eksperymentowania z WebTransport jest uruchomienie zgodnego serwera HTTP/3. Następnie możesz użyć tej strony z podstawowym klientem JavaScript, aby wypróbować komunikację klient-serwer.

Dodatkowo na stronie webtransport.day jest dostępny zarządzany przez społeczność serwer echa.

Korzystanie z interfejsu API

Protokół WebTransport został zaprojektowany w oparciu o nowoczesne elementy podstawowe platform internetowych, takie jak Streams API. Opiera się w dużej mierze na obietnicach i działa dobrze w async i await.

Obecna implementacja WebTransport w Chromium obsługuje trzy różne typy ruchu: datagramy, a także strumienie jednokierunkowe i dwukierunkowe.

Łączenie z serwerem

Możesz połączyć się z serwerem HTTP/3, tworząc instancję WebTransport. Schemat adresu URL powinien wyglądać tak: https. Musisz wyraźnie podać numer portu.

Użyj obietnicy ready w oczekiwaniu na nawiązanie połączenia. Ta obietnica nie zostanie zrealizowana, dopóki konfiguracja nie zostanie ukończona i zostanie odrzucona, jeśli nie uda się nawiązać połączenia na etapie QUIC/TLS.

Obietnica closed realizuje się w przypadku normalnego zamknięcia połączenia i odrzuca, jeśli zamknięcie było nieoczekiwane.

Jeśli serwer odrzuci połączenie z powodu błędu wskaźnika klienta (np. ścieżki adresu URL jest nieprawidłowa), spowoduje to odrzucenie żądania closed, ale rozwiązanie ready pozostaje nierozstrzygnięte.

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

Interfejsy API Datagramów

Po połączeniu instancji WebTransport z serwerem możesz jej używać do wysyłania i odbierania odrębnych bitów danych nazywanych datagramami.

Metoda pobierania writeable zwraca wartość WritableStream, za pomocą której klient internetowy może wysłać dane na serwer. Metoda pobierania readable zwraca wartość ReadableStream, co umożliwia nasłuchiwanie danych z serwera. Oba strumienie są z natury zawodne, więc możliwe, że dane, które zapiszesz, nie będą odbierane przez serwer i odwrotnie.

Oba rodzaje strumieni do przenoszenia danych używają instancji Uint8Array.

// Send two datagrams to the server.
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);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

Interfejsy API strumieni

Gdy połączysz się z serwerem, możesz też używać WebTransport do wysyłania i odbierania danych za pomocą interfejsów Streams API.

Każdy fragment wszystkich strumieni to Uint8Array. W przeciwieństwie do interfejsów Datagram API strumienie te są niezawodne. Jednak każdy strumień jest niezależny, więc kolejność danych w poszczególnych strumieniach nie jest gwarantowana.

WebTransportSendStream

Klient internetowy tworzy WebTransportSendStream przy użyciu metody createUnidirectionalStream() instancji WebTransport, która zwraca obietnicę dla WebTransportSendStream.

Użyj metody close() WritableStreamDefaultWriter, aby zamknąć powiązane połączenie HTTP/3. Przeglądarka próbuje wysłać wszystkie oczekujące dane, zanim faktycznie zamkniesz powiązane połączenie.

// Send two Uint8Arrays to the server.
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}`);
}

Podobnie użyj metody abort() WritableStreamDefaultWriter, aby wysłać RESET\_STREAM na serwer. Podczas korzystania z funkcji abort() przeglądarka może odrzucić wszelkie oczekujące dane, które nie zostały jeszcze wysłane.

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

Serwer zainicjował WebTransportReceiveStream. Uzyskiwanie WebTransportReceiveStream to proces dwuetapowy dla klienta internetowego. Najpierw wywołuje atrybut incomingUnidirectionalStreams wystąpienia WebTransport, który zwraca ReadableStream. Każdy fragment ReadableStream to z kolei WebTransportReceiveStream, który może służyć do odczytu instancji Uint8Array wysłanych przez serwer.

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

Zamknięcie strumienia możesz wykryć, korzystając z obietnicy closed dostępnej w ReadableStreamDefaultReader. Gdy podstawowe połączenie HTTP/3 jest zamknięte bitem FIN, obietnica closed jest osiągana po odczytaniu wszystkich danych. Gdy połączenie HTTP/3 zostanie nagle zamknięte (na przykład przez RESET\_STREAM), obietnica closed zostanie odrzucona.

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectionalStream

WebTransportBidirectionalStream może zostać utworzony przez serwer lub klienta.

Klienty internetowe mogą je utworzyć za pomocą metody createBidirectionalStream() instancji WebTransport, która zwraca obietnicę dla typu WebTransportBidirectionalStream.

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

Możesz nasłuchiwać zdarzenia WebTransportBidirectionalStream utworzonego przez serwer za pomocą atrybutu incomingBidirectionalStreams instancji WebTransport, który zwraca wartość ReadableStream. Każdy fragment ReadableStream to z kolei WebTransportBidirectionalStream.

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

Element WebTransportBidirectionalStream to po prostu kombinacja WebTransportSendStream i WebTransportReceiveStream. Przykłady z 2 poprzednich sekcji wyjaśniają, jak korzystać z każdej z nich.

Więcej przykładów

Specyfikacja robocza WebTransport zawiera szereg dodatkowych przykładów wbudowanych oraz pełną dokumentację wszystkich metod i właściwości.

WebTransport w Narzędziach deweloperskich w Chrome

Narzędzia deweloperskie w Chrome nie obsługują obecnie funkcji WebTransport. Aby otrzymywać powiadomienia o aktualizacjach w interfejsie Narzędzi deweloperskich, możesz oznaczyć oznaczeniem gwiazdką ten problem z Chrome.

Włókno poliestrowe

Dostępny jest moduł polyfill (a bardziej ponyfill, który działa jako osobny moduł) o nazwie webtransport-ponyfill-websocket i zaimplementujący niektóre funkcje WebTransport. Uważnie przeczytaj ograniczenia w obiekcie README projektu, aby określić, czy to rozwiązanie może sprawdzić się w Twoim przypadku użycia.

Kwestie związane z prywatnością i bezpieczeństwem

Wiarygodne wskazówki znajdziesz w odpowiedniej sekcji wersji roboczej specyfikacji.

Prześlij opinię

Zespół Chrome chce poznać Twoje przemyślenia i doświadczenia związane z tym interfejsem API.

Opinia na temat projektu interfejsu API

Czy interfejs API jest nietypowy lub nie działa zgodnie z oczekiwaniami? A może brakuje w nich elementów, które są niezbędne do realizacji pomysłu?

Zgłoś problem w repozytorium Web Transport GitHub lub dodaj swoje uwagi do istniejącego problemu.

Problem z implementacją?

Czy wystąpił błąd związany z implementacją przeglądarki Chrome?

Zgłoś błąd na stronie https://new.crbug.com. Podaj jak najwięcej szczegółów oraz proste instrukcje dotyczące odtworzenia.

Planujesz korzystać z interfejsu API?

Twoja publiczna pomoc pomaga Chrome priorytetowo traktować funkcje, a inni dostawcy przeglądarek pokazują, jak ważne jest ich wsparcie.

Dyskusja ogólna

W przypadku ogólnych pytań lub problemów, które nie pasują do żadnej z pozostałych kategorii, możesz skorzystać z grupy dyskusyjnej Google web-transport-dev.

Podziękowania

Ten artykuł zawiera informacje z WebTransport Explainer, wersji roboczej specyfikacji i powiązanej dokumentacji projektu. Dziękujemy twórcom za udostępnienie tych fundamentów.

Baner powitalny tego posta to Robin Pierre w aplikacji Unsplash.