WebTransport — это API, обеспечивающий двунаправленный обмен сообщениями между клиентом и сервером с малой задержкой. Узнайте больше о вариантах его использования и о том, как оставить отзыв о будущем его реализации.
Фон
Что такое WebTransport?
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
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.');
});
WebTransportBidirectionStream
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. Вы можете добавить эту проблему в звёздочку, чтобы получать уведомления об обновлениях интерфейса 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 для общих вопросов или проблем, которые не попадают ни в одну из других категорий.
Благодарности
В этой статье использованы материалы из WebTransport Explainer , проекта спецификации и сопутствующей проектной документации . Выражаем благодарность авторам за предоставление этой основы.
Главное изображение в этом посте принадлежит Робину Пьеру с Unsplash.