Использование каналов данных WebRTC
В этом руководстве мы рассмотрим, как добавить канал данных к подключению peer, который затем может использоваться для безопасного обмена произвольными данными; то есть любыми данными любого формата, который мы пожелаем.
Примечание: Поскольку все компоненты WebRTC обязаны использовать шифрование, любые данные, передаваемые по RTCDataChannel, автоматически защищаются с помощью Datagram Transport Layer Security (DTLS). Дополнительную информацию см. в разделе Безопасность ниже.
Создание канала данных
Базовая транспортная система данных, используемая RTCDataChannel, может быть создана двумя способами:
- Позвольте WebRTC создать транспорт и объявить его удаленному узлу (вызвав событие
datachannel). Это простой способ, который работает для широкого спектра случаев использования, но может оказаться недостаточно гибким для ваших потребностей. - Напишите свой собственный код для переговоров о транспортной системе данных и напишите свой собственный код для сигнализации другому узлу о необходимости подключения к новому каналу.
Давайте рассмотрим каждый из этих случаев, начиная с первого, который является наиболее распространенным.
Автоматические переговоры
Часто вы можете позволить подключению peer обрабатывать переговоры по подключению RTCDataChannel за вас. Для этого вызовите createDataChannel() без указания значения для свойства negotiated, или указав свойство со значением false. Это автоматически запустит RTCPeerConnection для обработки переговоров за вас, заставив удаленный узел создать канал данных и связать их вместе через сеть.
Объект RTCDataChannel возвращается сразу же методом createDataChannel(); вы можете определить, было ли подключение успешно, отслеживая событие open, которое отправляется в RTCDataChannel.
let dataChannel = pc.createDataChannel("MyApp Channel");
dataChannel.addEventListener("open", (event) => {
beginTransmission(dataChannel);
});
Ручные переговоры
Чтобы выполнить ручные переговоры по подключению канала данных, сначала необходимо создать новый объект RTCDataChannel с помощью метода createDataChannel() на объекте RTCPeerConnection, указав в параметрах свойство negotiated со значением true. Это указывает подключению peer на то, что оно не должно пытаться переговорить о канале от вашего имени.
Затем следует переговорить о подключении вне полосы, используя веб-сервер или другие средства. Этот процесс должен сигнализировать удаленному узлу о необходимости создать свой собственный RTCDataChannel со свойством negotiated также установленным в true, используя тот же id. Это соединит два объекта через RTCPeerConnection.
let dataChannel = pc.createDataChannel("MyApp Channel", {
negotiated: true,
});
dataChannel.addEventListener("open", (event) => {
beginTransmission(dataChannel);
});
requestRemoteChannel(dataChannel.id);
В этом фрагменте кода канал создается со значением negotiated установленным в true, а затем используется функция requestRemoteChannel() для запуска переговоров, чтобы создать удаленный канал с тем же идентификатором, что и локальный канал.
Это позволяет создавать каналы данных с каждым узлом, используя разные свойства, и объявлять каналы декларативно, используя одно и то же значение для id.
Буферизация
Каналы данных WebRTC поддерживают буферизацию исходящих данных. Это обрабатывается автоматически. Хотя вы не можете контролировать размер буфера, вы можете узнать, сколько данных в данный момент буферизуется, и вы можете выбрать уведомление об событии, когда буфер начнет испытывать нехватку данных в очереди. Это упрощает создание эффективных процедур, которые гарантируют, что всегда есть данные, готовые к отправке, без чрезмерного использования памяти или перегрузки канала.
Понимание ограничений размера сообщений
Для любых данных, передаваемых по сети, существуют ограничения размера. На фундаментальном уровне отдельные пакеты сети не могут быть больше определенного значения (точное число зависит от сети и используемого транспортного уровня). На уровне приложения — то есть в реализации WebRTC в пользовательском агенте, на котором работает ваш код — реализация WebRTC реализует функции для поддержки сообщений, размер которых больше, чем максимальный размер пакета в транспортном слое сети.
Это может усложнить ситуацию, поскольку вы не обязательно знаете ограничения размера для различных пользовательских агентов и как они реагируют при отправке или получении сообщения большего размера. Даже когда пользовательские агенты используют одну и ту же базовую библиотеку для обработки данных Stream Control Transmission Protocol (SCTP), могут существовать различия из-за того, как библиотека используется. Например, и Firefox, и Google Chrome используют библиотеку usrsctp для реализации SCTP, но все еще могут возникать ситуации, когда передача данных по RTCDataChannel может завершиться неудачно из-за различий в том, как они вызывают библиотеку и реагируют на возвращаемые ею ошибки.
Когда два пользователя, использующие Firefox, общаются через канал данных, предел размера сообщения намного больше, чем при общении Firefox и Chrome, потому что Firefox реализует сейчас устаревший метод отправки больших сообщений в нескольких сообщениях SCTP, чего Chrome не делает. Chrome вместо этого увидит серию сообщений, которые он посчитает полными, и передаст их получающему RTCDataChannel в виде нескольких сообщений.
Сообщения размером меньше 16 КБ можно отправлять без опасений, так как все основные пользовательские агенты обрабатывают их одинаково. За пределами этого ситуация становится сложнее.
Опасения в отношении больших сообщений
В настоящее время непрактично использовать RTCDataChannel для сообщений больше 64 КБ (16 КБ, если вы хотите обеспечить кроссбраузерный обмен данными). Проблема возникает из-за того, что SCTP — протокол, используемый для отправки и приема данных по RTCDataChannel — изначально был разработан для использования в качестве протокола сигнализации. Ожидалось, что сообщения будут относительно небольшими. Поддержка сообщений, размер которых превышает максимальный размер транспортного уровня сети (MTU), была добавлена практически как послеthought, на случай, если сообщения сигнализации должны быть больше, чем MTU. Эта функция требует, чтобы каждая часть сообщения имела последовательные порядковые номера, поэтому они должны передаваться одна за другой без каких-либо других данных между ними.
Это со временем стало проблемой. Со временем различные приложения (включая те, которые реализуют WebRTC) начали использовать SCTP для передачи все больших сообщений. В конечном счете, стало понятно, что когда сообщения становятся слишком большими, передача большого сообщения может заблокировать все другие передачи данных по этому каналу данных — включая важные сообщения сигнализации.
Эта проблема станет актуальной, когда браузеры должным образом поддержат текущий стандарт поддержки больших сообщений — флаг end-of-record (EOR), который указывает, когда сообщение является последним в серии, которая должна рассматриваться как единый полезный груз. Это реализовано в Firefox 57, но пока не реализовано в Chrome (см. Chromium Bug 7774). При наличии поддержки EOR полезные грузы RTCDataChannel могут быть значительно больше (официально до 256 КБ, но реализация Firefox ограничивает их внушительными 1 ГБ). Даже при 256 КБ этого достаточно, чтобы вызвать заметные задержки при обработке срочных данных. Если вы увеличите размер еще больше, задержки могут стать неприемлемыми, если вы не уверены в своих рабочих условиях.
Для решения этой проблемы была разработана новая система планировщиков потоков (обычно называемая «спецификацией SCTP ndata»), которая позволяет интерлировать сообщения, отправленные по разным потокам, включая потоки, используемые для реализации каналов данных WebRTC. Этот предложение все еще находится на стадии черновика IETF, но при его реализации станет возможным отправлять сообщения практически без ограничений размера, поскольку уровень SCTP автоматически будет интерлировать подсообщения, чтобы гарантировать, что данные каждого канала имеют возможность пройти.
Поддержка ndata в Firefox находится в стадии реализации; см. Firefox bug 1381145, чтобы отслеживать ее доступность для общего использования. Команда Chrome отслеживает свою реализацию поддержки ndata в Chrome Bug 5696.
Примечание: Большая часть информации в этом разделе частично основана на сообщении в блоге Demystifying WebRTC's Data Channel Message Size Limitations, написанном Lennart Grahl. Там он рассматривает вопрос более подробно, но поскольку с тех пор были обновлены браузеры, некоторые сведения могут быть устаревшими. Кроме того, со временем это будет еще более актуальным, особенно после того, как поддержка EOR и ndata будет полностью интегрирована в основные браузеры.
Безопасность
Все данные, передаваемые с помощью WebRTC, шифруются. В случае с RTCDataChannel, используемое шифрование — это Datagram Transport Layer Security (DTLS), основанное на Transport Layer Security (TLS). Поскольку TLS используется для защиты каждого подключения HTTPS, любые данные, которые вы отправляете по каналу данных, так же безопасны, как и любые другие данные, отправленные или полученные браузером пользователя.
Более фундаментально, так как WebRTC — это соединение peer-to-peer между двумя пользовательскими агентами, данные никогда не проходят через веб- или прикладной сервер. Это сокращает возможности перехвата данных.
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_data_channels