Signaling Server — це серверний компонент інфраструктури WebRTC, що забезпечує обмін метаданими між пірами для встановлення та завершення з’єднання. На відміну від медіатрафіку, сигналінг може передаватися будь-яким протоколом — WebSocket, HTTP, XMPP або SIP. Згідно з MDN Web Docs, 2024, сигналінг є обов’язковим компонентом будь-якого WebRTC-додатка, оскільки протокол не визначає конкретного способу обміну сигнальними повідомленнями.
Головне
Signaling Server — це мережевий сервіс, відповідальний за координацію процесу встановлення WebRTC-з’єднання між двома або більше пірами. Він не передає медіадані (аудіо, відео, дані DataChannel), а лише службову інформацію, необхідну для виявлення пірів та узгодження параметрів з’єднання. Після успішного встановлення P2P-каналу Signaling Server може бути більше не потрібний, але в деяких архітектурах він залишається для подальшого обміну сигналами (наприклад, завершення дзвінка, додавання учасників).
Архітектура сигналінгу включає три компоненти: Signaling Server, Signal Channel (транспортний протокол між клієнтом і сервером) та клієнтський API (зазвичай вбудований у стек WebRTC браузера). Специфікація WebRTC (W3C, 2024) навмисно не стандартизує сигнальний протокол — розробники можуть вибирати будь-який транспорт, що підходить для їхнього додатка. Це гнучке рішення дозволяє використовувати WebSocket для веб-додатків, XMPP для чат-систем або SIP для інтеграції з телекомунікаційною інфраструктурою.
Перед встановленням WebRTC-з’єднання піри повинні обмінятися трьома типами повідомлень: описами сесії (offer та answer), ICE кандидатами та інформацією про завершення/модифікацію сесії. Signaling Server маршрутизує ці повідомлення між пірами, використовуючи ідентифікатори кімнат або користувачів для адресації. Стандартний патерн — створення “кімнати”, куди підключаються два учасники, і сервер ретранслює повідомлення від кожного учасника лише його співрозмовнику.
Signaling Server реалізує наступний типовий протокол встановлення WebRTC-з’єднання. Піри підключаються до сервера через WebSocket (або інший транспорт) і реєструються в кімнаті. Пір A (ініціатор) створює offer (SDP-опис вихідного медіапотоку) через RTCPeerConnection.createOffer(), встановлює його як локальний опис і надсилає на Signaling Server. Сервер ретранслює offer піру B. Пір B отримує offer, встановлює його як віддалений опис, створює answer через createAnswer(), встановлює його як локальний опис і надсилає назад через сервер. Цей процес називається SDP Offer/Answer.
Паралельно з обміном SDP кожен пір збирає ICE кандидатів (host, srflx, relay) і надсилає їх через Signaling Server іншому піру. Віддалений пір додає отриманих кандидатів через RTCPeerConnection.addIceCandidate(). ICE-процес перевіряє всі комбінації кандидатів для пошуку працюючого шляху. Після того як знайдено працюючий шлях (зазвичай за 1–5 секунд), медіатрафік починає передаватися безпосередньо між пірами, і Signaling Server більше не бере участі в передачі даних — його роль завершена до наступної службової події (завершення дзвінка, зміна якості потоку).
Для адресації повідомлень Signaling Server використовує механізм кімнат (rooms) або каналів. Кожен новий сеанс WebRTC створює унікальну кімнату з ідентифікатором (зазвичай UUID). Ініціатор створює кімнату та очікує підключення другого піра. Другий пір підключається до кімнати за ID, отриманим через зовнішній канал (наприклад, посилання-запрошення). Сервер підтримує мапу кімнат, де кожному ID відповідає список підключених клієнтів. Коли кількість учасників досягає двох, сервер починає ретранслювати сигнальні повідомлення між ними.
Signaling Server може використовувати різні транспортні протоколи, кожен із яких має свої переваги та недоліки. Вибір протоколу залежить від типу додатка, інфраструктурних обмежень та вимог до сумісності. Нижче наведено найпоширеніші протоколи та їхні характеристики.
| Протокол | Транспорт | Переваги | Недоліки |
|---|---|---|---|
| WebSocket | TCP | Повнодуплексний, низька затримка, вбудований у браузери | Складність масштабування, блокування проксі |
| HTTP/SSE | TCP | Сумісність з будь-якою інфраструктурою, простота реалізації | Лише однонаправлений (сервер-клієнт), потрібен Polling |
| XMPP | TCP | Стандартизований, підтримка аутентифікації, розширюваний | Надлишковий для простих сценаріїв, XML-overhead |
| SIP | UDP/TCP | Інтеграція з VoIP та телефонною інфраструктурою | Складний, не нативний для браузерів |
| MQTT | TCP | Легкий, працює в IoT-середовищах, publish/subscribe | Потрібен брокер, додаткова затримка |
WebSocket є найпопулярнішим протоколом для Signaling Server у веб-додатках. Він забезпечує повнодуплексний зв’язок, що важливо для асинхронного обміну SDP та ICE кандидатами, і нативно підтримується всіма сучасними браузерами через WebSocket API. Серверна реалізація WebSocket доступна на всіх популярних платформах (Node.js, Python, Java, Go). Для додатків з мільйонами користувачів використовуються масштабовані WebSocket-рішення на базі Redis Pub/Sub або Kafka для синхронізації між інстансами Signaling Server.
Розглянемо просту реалізацію Signaling Server на Node.js з використанням бібліотеки ws (WebSocket) та вбудованого HTTP-сервера. Сервер підтримує реєстрацію користувачів, створення кімнат та ретрансляцію повідомлень між учасниками.
const WebSocket = require("ws");
const server = new WebSocket.Server({ port: 8080 });
const rooms = new Map();
server.on("connection", (ws) => {
ws.roomId = null;
ws.on("message", (data) => {
const msg = JSON.parse(data);
switch (msg.type) {
case "join":
handleJoin(ws, msg.roomId);
break;
case "offer":
case "answer":
case "ice-candidate":
relayToPeer(ws, msg);
break;
case "leave":
handleLeave(ws);
break;
}
});
ws.on("close", () => handleLeave(ws));
});
function handleJoin(ws, roomId) {
if (!rooms.has(roomId)) {
rooms.set(roomId, []);
}
const room = rooms.get(roomId);
room.push(ws);
ws.roomId = roomId;
if (room.length === 2) {
room[0].send(JSON.stringify({ type: "peer-joined" }));
room[1].send(JSON.stringify({ type: "peer-joined" }));
}
}
function relayToPeer(sender, msg) {
const room = rooms.get(sender.roomId);
if (!room) return;
room.forEach(peer => {
if (peer !== sender && peer.readyState === WebSocket.OPEN) {
peer.send(JSON.stringify(msg));
}
});
}
function handleLeave(ws) {
if (!ws.roomId) return;
const room = rooms.get(ws.roomId);
if (!room) return;
const idx = room.indexOf(ws);
if (idx !== -1) room.splice(idx, 1);
if (room.length === 0) rooms.delete(ws.roomId);
}
Цей Signaling Server реалізує базову функціональність: підключення до кімнати, ретрансляцію WebRTC-повідомлень (offer, answer, ice-candidate) між двома пірами та управління відключеннями. Сервер використовує Map для зберігання кімнат з підключеними WebSocket-клієнтами. Функція relayToPeer надсилає повідомлення всім учасникам кімнати, крім відправника. Для продакшну потрібно додати підтвердження типів повідомлень, обробку помилок парсингу JSON та механізм heartbeat для виявлення розірваних з’єднань.
На стороні клієнта Signaling Server інтегрується через WebSocket API браузера. Клієнт встановлює з’єднання з сервером, надсилає запит на приєднання до кімнати, а потім обробляє вхідні WebRTC-повідомлення, передаючи їх у RTCPeerConnection через setRemoteDescription() та addIceCandidate(). Клієнтський код також надсилає на сервер свої SDP та ICE кандидати, отримані від RTCPeerConnection через події onicecandidate та після створення offer/answer.
Signaling Server передає два ключових типи метаданих: SDP (Session Description Protocol) та ICE кандидати. SDP описує параметри медіапотоку — кодеки, частоту дискретизації, кількість каналів, напрямок передачі (sendrecv, sendonly, recvonly, inactive). ICE кандидати містять мережеві адреси (локальні, отримані від STUN, релейні від TURN), за якими пір може бути доступний для з’єднання.
SDP представлений у текстовому форматі, що містить сесії та медіасекції. Сесійна частина описує загальні параметри (ідентифікатор сесії, версія, назва), медіасекції — кожен медіапотік (аудіо, відео, DataChannel) з його кодеком, портом та протоколом. ICE кандидати містять foundation (ідентифікатор для групування), priority, IP-адресу, порт, тип (host, srflx, relay) та протокол (UDP, TCP). Кожен кандидат також включає атрибут ufrag (username fragment), що пов’язує його з конкретним ICE-процесом.
Trickle ICE значно прискорює встановлення WebRTC-з’єднання. Замість очікування повного збору всіх ICE кандидатів (що може займати 2–10 секунд у складних мережах), кожен кандидат надсилається на Signaling Server негайно після виявлення. Віддалений пір отримує кандидата і тут же починає перевірку з’єднання через ICE-фреймворк. Це скорочує час встановлення з’єднання до 500–1500 мс у більшості випадків.
Часті запитання
Signaling Server — це “координатор” перед дзвінком. Він допомагає двом пристроям знайти один одного і домовитися про те, як вони будуть спілкуватися. Після того як пристрої “познайомилися” і домовилися, сервер більше не потрібен — вони спілкуються безпосередньо.
WebRTC не визначає протокол сигналінгу, щоб розробники могли вибрати найбільш підходящий транспорт. Браузер не має вбудованого механізму для виявлення інших користувачів — це завдання вирішує Signaling Server. Він служить “поштарем”, передаючи запрошення та налаштування з’єднання між учасниками дзвінка.
WebSocket — оптимальний вибір для більшості веб-додатків: повнодуплексний, нативно підтримується браузерами, простий у реалізації. Для інтеграції з існуючою VoIP-інфраструктурою вибирайте SIP. Для чат-додатків з багатими функціями — XMPP. Для IoT-сценаріїв — MQTT.
Для масштабування Signaling Server використовуйте горизонтальне масштабування з синхронізацією через Redis Pub/Sub або Kafka. Кожен серверний інстанс обробляє свою частку WebSocket-з’єднань, а для міжсерверної маршрутизації повідомлень використовується загальна шина даних. Цей підхід дозволяє обробляти мільйони одночасних сигнальних сесій.
Signaling Server критичний лише на етапі встановлення з’єднання. Якщо сервер тимчасово недоступний, активні WebRTC-дзвінки продовжуються — медіатрафік йде безпосередньо між пірами. Проблема виникає лише при спробі встановити нове з’єднання. Для надійності використовуйте кластеризацію серверів та резервні канали сигналінгу.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.