WebTransport — это API, обеспечивающий двунаправленный обмен сообщениями клиент-сервер с малой задержкой. Узнайте больше о вариантах его использования и о том, как оставить отзыв о будущем реализации.
Фон
Что такое веб-транспорт?
WebTransport — это веб-API, использующий протокол HTTP/3 в качестве двунаправленного транспорта. Он предназначен для двусторонней связи между веб-клиентом и сервером HTTP/3. Он поддерживает отправку данных как ненадежно через API-интерфейсы датаграмм , так и надежно через API-интерфейсы потоков .
Дейтаграммы идеально подходят для отправки и получения данных, не требующих надежных гарантий доставки. Отдельные пакеты данных ограничены по размеру максимальной единицей передачи (MTU) базового соединения и могут передаваться или не передаваться успешно, а если они передаются, они могут поступать в произвольном порядке. Эти характеристики делают API-интерфейсы датаграмм идеальными для передачи данных с малой задержкой и с максимальной эффективностью. Дейтаграммы можно рассматривать как сообщения протокола пользовательских датаграмм (UDP) , но зашифрованные и управляемые перегрузкой.
API потоков, напротив, обеспечивают надежную упорядоченную передачу данных. Они хорошо подходят для сценариев, когда вам необходимо отправить или получить один или несколько потоков упорядоченных данных. Использование нескольких потоков WebTransport аналогично установлению нескольких TCP- соединений, но поскольку HTTP/3 внутри использует более легкий протокол QUIC , их можно открывать и закрывать без особых накладных расходов.
Варианты использования
Это небольшой список возможных способов использования WebTransport разработчиками.
- Отправка состояния игры на сервер через регулярные промежутки времени с минимальной задержкой с помощью небольших, ненадежных сообщений, находящихся вне очереди.
- Получение медиапотоков, передаваемых с сервера, с минимальной задержкой, независимо от других потоков данных.
- Получение уведомлений, отправленных с сервера, когда веб-страница открыта.
Нам интересно узнать больше о том, как вы планируете использовать WebTransport.
Поддержка браузера
Как и в случае со всеми функциями, которые не имеют универсальной поддержки браузера, передовой практикой является защитное кодирование с помощью обнаружения функций .
Текущий статус
Шаг | Статус |
---|---|
1. Создайте объяснитель | Полный |
2. Создайте первоначальный проект спецификации. | Полный |
3. Соберите отзывы и повторите дизайн | Полный |
4. Пробная версия происхождения | Полный |
5. Запуск | Хром 97 |
Связь WebTransport с другими технологиями
Является ли WebTransport заменой WebSockets?
Может быть. Существуют случаи использования, когда допустимыми протоколами связи могут быть либо WebSockets , либо WebTransport.
Коммуникации WebSockets моделируются на основе единого надежного упорядоченного потока сообщений, что подходит для некоторых типов коммуникационных потребностей. Если вам нужны эти характеристики, то API потоков WebTransport также могут их предоставить. Для сравнения, API дейтаграмм WebTransport обеспечивают доставку с малой задержкой, без гарантий надежности или порядка, поэтому они не являются прямой заменой WebSockets.
Использование WebTransport через API дейтаграмм или через несколько одновременных экземпляров API Streams означает, что вам не нужно беспокоиться о блокировке начала строки , которая может быть проблемой с WebSockets. Кроме того, при установке новых соединений повышается производительность, поскольку базовое подтверждение QUIC происходит быстрее, чем запуск TCP через TLS.
WebTransport является частью нового проекта спецификации, и поэтому экосистема WebSocket вокруг клиентских и серверных библиотек в настоящее время намного более надежна. Если вам нужно что-то, что работает «из коробки» с обычными настройками сервера и с широкой поддержкой веб-клиентов, WebSockets сегодня является лучшим выбором.
Является ли WebTransport тем же самым, что и API сокетов UDP?
Нет. WebTransport не является API сокетов UDP . В то время как WebTransport использует HTTP/3, который, в свою очередь, использует UDP «под капотом», у WebTransport есть требования к шифрованию и контролю перегрузки, которые делают его чем-то большим, чем просто базовый API сокетов UDP.
Является ли WebTransport альтернативой каналам передачи данных WebRTC?
Да, для клиент-серверных соединений. WebTransport имеет многие из тех же свойств, что и каналы данных WebRTC , хотя базовые протоколы отличаются.
Как правило, для запуска HTTP/3-совместимого сервера требуется меньше настроек и настроек, чем для обслуживания сервера WebRTC, что предполагает понимание нескольких протоколов ( ICE , DTLS и SCTP ) для получения рабочего транспорта. WebRTC влечет за собой множество других важных моментов, которые могут привести к неудачным переговорам между клиентом и сервером.
API WebTransport был разработан с учетом вариантов использования веб-разработчиков и должен больше напоминать написание кода современной веб-платформы, чем использование интерфейсов каналов данных WebRTC. В отличие от WebRTC , WebTransport поддерживается внутри Web Workers , что позволяет вам осуществлять связь клиент-сервер независимо от данной HTML-страницы. Поскольку WebTransport предоставляет интерфейс, совместимый со Streams , он поддерживает оптимизацию противодавления .
Однако, если у вас уже есть работающая настройка клиента/сервера WebRTC, которая вас устраивает, переход на WebTransport может не дать много преимуществ.
Попробуйте это
Лучший способ поэкспериментировать с WebTransport — запустить совместимый сервер HTTP/3. Затем вы можете использовать эту страницу с базовым клиентом JavaScript, чтобы опробовать связь клиент/сервер.
Кроме того, эхо-сервер, поддерживаемый сообществом, доступен по адресу webtransport.day .
Использование API
WebTransport был разработан на основе современных примитивов веб-платформы, таких как Streams API . Он в значительной степени полагается на обещания и хорошо работает с async
и await
.
Текущая реализация WebTransport в Chromium поддерживает три различных типа трафика: дейтаграммы, а также однонаправленные и двунаправленные потоки.
Подключение к серверу
Вы можете подключиться к серверу HTTP/3, создав экземпляр WebTransport
. Схема URL должна быть https
. Вам необходимо явно указать номер порта.
Вам следует использовать ready
обещание и дождаться установления соединения. Это обещание не будет выполнено до завершения настройки и будет отклонено в случае сбоя соединения на этапе QUIC/TLS.
closed
обещание выполняется, когда соединение закрывается нормально, и отклоняется, если закрытие было неожиданным.
Если сервер отклоняет соединение из-за ошибки указания клиента (например, неверный путь URL-адреса), то это приводит к отклонению соединения closed
, а ready
остается неразрешенной.
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;
Дейтаграммные API
Если у вас есть экземпляр WebTransport, подключенный к серверу, вы можете использовать его для отправки и получения отдельных битов данных, известных как дейтаграммы .
writeable
метод получения возвращает WritableStream
, который веб-клиент может использовать для отправки данных на сервер. readable
метод получения возвращает ReadableStream
, что позволяет вам прослушивать данные с сервера. Оба потока по своей сути ненадежны, поэтому вполне возможно, что записываемые вами данные не будут получены сервером, и наоборот.
Оба типа потоков используют экземпляры 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);
}
API потоков
После подключения к серверу вы также можете использовать WebTransport для отправки и получения данных через его API-интерфейсы Streams.
Каждый фрагмент всех потоков представляет собой Uint8Array
. В отличие от API-интерфейсов Datagram, эти потоки надежны. Но каждый поток независим, поэтому порядок данных в потоках не гарантируется.
ВебТранспортСендСтрим
WebTransportSendStream
создается веб-клиентом с помощью метода createUnidirectionalStream()
экземпляра WebTransport
, который возвращает обещание для WebTransportSendStream
.
Используйте метод close()
класса WritableStreamDefaultWriter
, чтобы закрыть связанный поток HTTP/3. Браузер пытается отправить все ожидающие данные, прежде чем фактически закрыть связанный поток.
// 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}`);
}
Аналогичным образом используйте метод abort()
класса WritableStreamDefaultWriter
для отправки RESET_STREAM
на сервер. При использовании abort()
браузер может отбросить любые ожидающие данные, которые еще не были отправлены.
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
WebTransportReceiveStream
инициируется сервером. Получение WebTransportReceiveStream
— это двухэтапный процесс для веб-клиента. Сначала он вызывает атрибут incomingUnidirectionalStreams
экземпляра WebTransport
, который возвращает ReadableStream
. Каждый фрагмент этого ReadableStream
, в свою очередь, является WebTransportReceiveStream
, который можно использовать для чтения экземпляров Uint8Array
, отправленных сервером.
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);
}
Вы можете обнаружить закрытие потока, используя closed
обещание ReadableStreamDefaultReader
. Когда базовый поток HTTP/3 закрывается битом FIN , closed
обещание выполняется после считывания всех данных. Когда поток HTTP/3 внезапно закрывается (например, с помощью RESET_STREAM
), closed
обещание отклоняется.
// 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.');
});
WebTransportДвунаправленный поток
WebTransportBidirectionalStream
может быть создан либо сервером, либо клиентом.
Веб-клиенты могут создать его с помощью метода createBidirectionalStream()
экземпляра WebTransport
, который возвращает обещание для WebTransportBidirectionalStream
.
const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream
Вы можете прослушивать WebTransportBidirectionalStream
созданный сервером, с помощью атрибута incomingBidirectionalStreams
экземпляра WebTransport
, который возвращает ReadableStream
. Каждый фрагмент этого ReadableStream
, в свою очередь, является 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
}
WebTransportBidirectionalStream
— это просто комбинация WebTransportSendStream
и WebTransportReceiveStream
. Примеры из двух предыдущих разделов объясняют, как использовать каждый из них.
Больше примеров
Черновой вариант спецификации WebTransport включает ряд дополнительных встроенных примеров, а также полную документацию по всем методам и свойствам.
WebTransport в DevTools Chrome
К сожалению, DevTools Chrome в настоящее время не поддерживает WebTransport. Вы можете пометить эту проблему Chrome , чтобы получать уведомления об обновлениях интерфейса DevTools.
Полифилл
Доступен полифил (или, скорее, понифил, который предоставляет функциональность в качестве отдельного модуля, который вы можете использовать) под названием webtransport-ponyfill-websocket
, который реализует некоторые функции WebTransport. Внимательно прочитайте ограничения в README
проекта, чтобы определить, подойдет ли это решение для вашего варианта использования.
Соображения конфиденциальности и безопасности
См. соответствующий раздел проекта спецификации для получения авторитетных рекомендаций.
Обратная связь
Команда Chrome хочет услышать ваши мысли и опыт использования этого API.
Отзыв о дизайне API
Есть ли что-то в API неудобное или не работает должным образом? Или есть недостающие детали, необходимые для реализации вашей идеи?
Сообщите о проблеме в репозитории Web Transport GitHub или добавьте свои мысли к существующей проблеме.
Проблема с реализацией?
Вы нашли ошибку в реализации Chrome?
Сообщите об ошибке на https://new.crbug.com . Включите как можно больше деталей, а также простые инструкции по воспроизведению.
Планируете использовать API?
Ваша публичная поддержка помогает Chrome расставлять приоритеты для функций и показывает другим поставщикам браузеров, насколько важно их поддерживать.
- Отправьте твит @ChromiumDev, используя хэштег
#WebTransport
и указав подробную информацию о том, где и как вы его используете.
Общее обсуждение
Вы можете использовать группу Google web-transport-dev для решения общих вопросов или проблем, которые не вписываются ни в одну из других категорий.
Благодарности
Эта статья включает в себя информацию из WebTransportExplainer , черновых спецификаций и сопутствующей проектной документации . Спасибо соответствующим авторам за предоставление этой основы.
Изображение героя в этом посте принадлежит Робину Пьеру из Unsplash.