WebRTC позволяет браузерам обмениваться информацией напрямую без сервера. Можно передавать видео, звук и данные. Установить WebRTC соединение можно разными способами. В статье описано как WebRTC соединение устанавливается между пользователями редактора схем dgrm.net.
В DGRM клиенты не соединяются “каждый с каждым”. События клиентам рассылает браузер инициатора встречи
Когда пользователь добавляет фигуру, меняет цвет или двигает курсор - данные о событии по WebRTC отправляются браузеру инициатора встречи. Инициатор пересылает данные другим пользователям.
Для соединения по WebRTC браузеры должны обменяться параметрами соединения
Когда клиент подключается к инициатору, он должен сообщить инициатору параметры соединения: требования к соединению и свои сетевые адреса.
Пример требований к соединению: должно ли соединение поддерживать видео, какой кодек использовать и т.п. DGRM передает только JSON-строки.
Сетевых адресов у клиента может быть несколько. Например, один адрес в локальной сети, другой - во внешней. Если клиент и инициатор встречи в одной локальной сети - для соединения будет использоваться адрес в локальной сети. Адрес во внешней сети браузер сам узнать не может. Для получения своего внешнего адреса браузер делает запрос к специальному STUN серверу. STUN сервер возвращает браузеру его внешние адреса. Есть бесплатные STUN сервера, например у Google. Хорошая статья о том, как устроена адресация в WebRTC: Просто о WebRTC (forasoft.github.io).
Параметры соединения, которые клиент передает при подключении, называются SDPOffer. Инициатор встречи на основе SDPOffer формирует и отправляет клиенту SDPAnswer. SDPAnswer содержит сетевые адреса инициатора.
Обмен параметрами WebRTC соединения через свой сервер
Обменяться параметрами соединения можно разными способами. Например вручную через мессенджер. SDPOffer и SDPOffer - это строки. С помощью JavaScript и API браузера можно получить SDPOffer/SDPAnswer, вывести на страницу, скопировать и отправить в мессенджер.
v=0
o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
s=
c=IN IP4 host.atlanta.example.com
t=0 0
m=audio 49170 RTP/AVP 0 8 97
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:97 iLBC/8000
m=video 51372 RTP/AVP 31 32
a=rtpmap:31 H261/90000
a=rtpmap:32 MPV/90000
Листинг 1. Пример SDPOffer. SDPOffer и SDPAnswer это строки
В DGRM для обмена параметрами соединения используется свой сервер.
Когда инициатор встречи нажимает “Live collaboration”:
Браузер инициатора отправляет на сервер DGRM запрос “создать встречу”. При этом передается случайный id встречи.
Сервер запоминает id встречи.
Инициатор отправляет ссылку с id встречи через мессенджер.
Клиент проходит по ссылке.
Браузер клиента генерирует SDPOffer. Отправляет id встречи, свой id клиента и SDPOffer на сервер.
Сервер запоминает SDPOffer.
Браузер инициатора периодически опрашивает сервер “дай SDPOffer-ы для id встречи”.
Браузер инициатора при получении SDPOffer генерирует SDPAnswer. Посылает id встречи, id клиента и SDPAnswer на сервер.
Сервер запоминает SDPAnswer
Браузер клиента после паузы запрашивает у сервера SDPAnswer.
Как только клиент получает SDPAnswer, устанавливается WebRTC соединение.
Уточнения к схеме
Почему для обмена SDPOffer/SDPAnswer не используются web-сокеты?
Здесь используются периодические опросы сервера. WebRTC соединение устанавливается за пару секунд. Если использовать web-сокеты или server-events, то WebRTC соединение будет устанавливаться быстрее. Зато в такой схеме меньше требования к серверу.
Почему инициатор не может отправить клиенту SDPAnswer сразу по WebRTC?
Инициатор получил SDPOffer. SDPOffer содержит адреса клиента. Почему не отправить SDPAnswer сразу клиенту? Не знаю. У меня не получилось. Спрашивал в группах по WebRTC, говорят так нельзя.
Почему SDPOffer делает клиент, а не инициатор?
Инициатор может сделать один SDPOffer для всех клиентов. Тогда схема обмена упростится. Почему так не сделано? Инициатор должен иметь WebRTC соединение с каждым клиентом. Одни SDPOffer нельзя использовать в нескольких соединениях.
Я не хочу делать свою реализацию. Есть готовые решения?
Есть сервисы для разработчиков которые не только производят обмен SDPOffer/SDPAnswer, но и предлагают TURN сервер. Если соединение p2p не удается установить, данные начинают отправляться через TURN сервер. TURN - это запасной вариант.