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 везе, пирови морају да размене три врсте порука: session description (offer и answer), ICE candidates и информације о завршетку/модификацији сесије. Signaling Server усмерава ове поруке између пирова, користећи идентификаторе соба или корисника за адресирање. Стандардни образац — креирање „собе“ у коју се повезују два учесника, а сервер ретрансмитује поруке од сваког учесника само његовом саговорнику.
Signaling Server имплементира следећи типични протокол успостављања WebRTC везе. Пирови се повезују на сервер преко WebSocket (или другог транспорта) и региструју се у соби. Пир A (иницијатор) креира offer (SDP опис излазног медијског тока) преко RTCPeerConnection.createOffer(), поставља га као local description и шаље на Signaling Server. Сервер ретрансмитује offer пиру B. Пир B прима offer, поставља га као remote description, креира answer преко createAnswer(), поставља га као local description и шаље назад преко сервера. Овај процес се назива SDP Offer/Answer.
Упоредо са разменом SDP, сваки пир прикупља ICE candidates (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 оптерећење |
| 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 candidates. SDP описује параметре медијског тока — кодеци, фреквенција одабирања, број канала, правац преноса (sendrecv, sendonly, recvonly, inactive). ICE candidates садрже мрежне адресе (локалне, добијене од STUN, релејне од TURN) преко којих пир може бити доступан за везу.
SDP је представљен у текстуалном формату који садржи сесије и медијске секције. Део сесије описује опште параметре (идентификатор сесије, верзија, назив), медијске секције — сваки медијски ток (аудио, видео, DataChannel) са својим кодеком, портом и протоколом. ICE кандидати садрже foundation (идентификатор за груписање), priority, IP адресу, порт, тип (host, srflx, relay) и протокол (UDP, TCP). Сваки candidate такође укључује атрибут ufrag (username fragment) који га повезује са конкретним ICE процесом.
Trickle ICE значајно убрзава успостављање WebRTC везе. Уместо чекања на потпуно прикупљање свих ICE кандидата (што може трајати 2–10 секунди у сложеним мрежама), сваки кандидат се шаље на Signaling Server одмах након откривања. Удаљени пир прима кандидата и одмах почиње проверу везе кроз ICE оквир. Ово смањује време успостављања везе на 500–1500 ms у већини случајева.
Често постављана питања
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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође