Signaling Server — is een servercomponent van de WebRTC-infrastructuur die zorgt voor de uitwisseling van metadata tussen peers voor het opzetten en beëindigen van een verbinding. In tegenstelling tot mediaverkeer kan signalering worden verzonden via elk protocol — WebSocket, HTTP, XMPP of SIP. Volgens MDN Web Docs, 2024 is signalering een verplicht onderdeel van elke WebRTC-applicatie, omdat het protocol geen specifieke manier voor het uitwisselen van signaleringsberichten definieert.
Belangrijkste punten
Signaling Server — is een netwerkdienst die verantwoordelijk is voor de coördinatie van het proces van het opzetten van een WebRTC-verbinding tussen twee of meer peers. Het verzendt geen mediadata (audio, video, DataChannel-kanaalgegevens), maar alleen service-informatie die nodig is voor het detecteren van peers en het onderhandelen over verbindingsparameters. Nadat het P2P-kanaal met succes is opgezet, is de Signaling Server mogelijk niet meer nodig, maar in sommige architecturen blijft deze bestaan voor latere signaaluitwisseling (bijvoorbeeld het beëindigen van een gesprek, het toevoegen van deelnemers).
De signaleringsarchitectuur omvat drie componenten: Signaling Server, Signal Channel (transportprotocol tussen client en server) en client-API (meestal ingebouwd in de WebRTC-stack van de browser). De WebRTC-specificatie (W3C, 2024) standaardiseert opzettelijk het signaalprotocol niet — ontwikkelaars kunnen elk transport kiezen dat geschikt is voor hun applicatie. Deze flexibele oplossing maakt het mogelijk om WebSocket te gebruiken voor webapplicaties, XMPP voor chatsystemen of SIP voor integratie met telecommunicatie-infrastructuur.
Voordat de WebRTC-verbinding tot stand wordt gebracht, moeten peers drie soorten berichten uitwisselen: session description (offer en answer), ICE candidates en informatie over het beëindigen/wijzigen van de sessie. De Signaling Server routeert deze berichten tussen peers, met behulp van kamer- of gebruikers-ID's voor adressering. Het standaardpatroon — het creëren van een “kamer” waar twee deelnemers verbinding mee maken, en de server stuurt berichten van elke deelnemer alleen door naar diens gesprekspartner.
Signaling Server implementeert het volgende typische protocol voor het opzetten van een WebRTC-verbinding. Peers maken via WebSocket (of ander transport) verbinding met de server en registreren zich in een kamer. Peer A (de initiatiefnemer) maakt een offer (SDP-beschrijving van de uitgaande mediastroom) via RTCPeerConnection.createOffer(), stelt dit in als local description en stuurt het naar de Signaling Server. De server stuurt het offer door naar peer B. Peer B ontvangt het offer, stelt dit in als remote description, maakt een answer via createAnswer(), stelt dit in als local description en stuurt het terug via de server. Dit proces heet SDP Offer/Answer.
Parallel aan de SDP-uitwisseling verzamelt elke peer ICE candidates (host, srflx, relay) en stuurt deze via de Signaling Server naar de andere peer. De externe peer voegt de ontvangen kandidaten toe via RTCPeerConnection.addIceCandidate(). Het ICE-proces controleert alle combinaties van kandidaten om een werkend pad te vinden. Nadat een werkend pad is gevonden (meestal binnen 1–5 seconden), begint het mediaverkeer direct tussen peers te worden verzonden en neemt de Signaling Server niet langer deel aan de gegevensoverdracht — zijn rol is voltooid tot de volgende servicegebeurtenis (beëindigen gesprek, wijzigen kwaliteit van de stroom).
Voor het adresseren van berichten gebruikt de Signaling Server een mechanisme van kamers (rooms) of kanalen. Elke nieuwe WebRTC-sessie creëert een unieke kamer met een identificatie (meestal UUID). De initiatiefnemer creëert een kamer en wacht op verbinding van de tweede peer. De tweede peer maakt verbinding met de kamer via een ID dat via een extern kanaal (bijvoorbeeld een uitnodigingslink) is verkregen. De server onderhoudt een kaart van kamers, waarbij elk ID overeenkomt met een lijst van verbonden clients. Wanneer het aantal deelnemers twee bereikt, begint de server signaleringsberichten tussen hen door te sturen.
Signaling Server kan verschillende transportprotocollen gebruiken, elk met zijn eigen voor- en nadelen. De keuze van het protocol hangt af van het type applicatie, infrastructurele beperkingen en compatibiliteitsvereisten. Hieronder staan de meest voorkomende protocollen en hun kenmerken.
| Protocol | Transport | Voordelen | Nadelen |
|---|---|---|---|
| WebSocket | TCP | Full-duplex, lage latentie, ingebouwd in browsers | Complexiteit van schalen, proxy-blokkering |
| HTTP/SSE | TCP | Compatibiliteit met elke infrastructuur, eenvoud van implementatie | Alleen unidirectioneel (server-client), vereist Polling |
| XMPP | TCP | Gestandaardiseerd, ondersteuning voor authenticatie, uitbreidbaar | Overbodig voor eenvoudige scenario's, XML-overhead |
| SIP | UDP/TCP | Integratie met VoIP en telefooninfrastructuur | Complex, niet-native voor browsers |
| MQTT | TCP | Lichtgewicht, werkt in IoT-omgevingen, publish/subscribe | Vereist broker, extra latentie |
WebSocket is het populairste protocol voor Signaling Server in webapplicaties. Het biedt full-duplex communicatie, wat belangrijk is voor asynchrone uitwisseling van SDP- en ICE-kandidaten, en wordt native ondersteund door alle moderne browsers via de WebSocket API. De serverimplementatie van WebSocket is beschikbaar op alle populaire platforms (Node.js, Python, Java, Go). Voor applicaties met miljoenen gebruikers worden schaalbare WebSocket-oplossingen op basis van Redis Pub/Sub of Kafka gebruikt voor synchronisatie tussen Signaling Server-instanties.
Laten we een eenvoudige implementatie van Signaling Server in Node.js bekijken met behulp van de ws-bibliotheek (WebSocket) en de ingebouwde HTTP-server. De server ondersteunt gebruikersregistratie, het creëren van kamers en het doorsturen van berichten tussen deelnemers.
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);
}
Deze Signaling Server implementeert basisfunctionaliteit: verbinding maken met een kamer, het doorsturen van WebRTC-berichten (offer, answer, ice-candidate) tussen twee peers en het beheren van verbrekingen. De server gebruikt Map voor het opslaan van kamers met verbonden WebSocket-clients. De functie relayToPeer stuurt een bericht naar alle deelnemers in de kamer, behalve de afzender. Voor productie moet bevestiging van berichttypen, foutafhandeling van JSON-parsing en een heartbeat-mechanisme voor het detecteren van verbroken verbindingen worden toegevoegd.
Aan de clientzijde wordt Signaling Server geïntegreerd via de WebSocket API van de browser. De client maakt verbinding met de server, stuurt een verzoek om deel te nemen aan een kamer en verwerkt vervolgens inkomende WebRTC-berichten door ze door te geven aan RTCPeerConnection via setRemoteDescription() en addIceCandidate(). De clientcode stuurt ook zijn eigen SDP- en ICE-kandidaten naar de server, verkregen van RTCPeerConnection via gebeurtenissen onicecandidate en na het creëren van offer/answer.
Signaling Server verzendt twee belangrijke soorten metadata: SDP (Session Description Protocol) en ICE candidates. SDP beschrijft de parameters van de mediastroom — codecs, bemonsteringsfrequentie, aantal kanalen, transmissierichting (sendrecv, sendonly, recvonly, inactive). ICE candidates bevatten netwerkadressen (lokaal, verkregen van STUN, relay van TURN) waarop een peer bereikbaar is voor verbinding.
SDP wordt gepresenteerd in tekstformaat dat sessies en mediasecties bevat. Het sessiegedeelte beschrijft algemene parameters (sessie-ID, versie, naam), de mediasecties — elke mediastroom (audio, video, DataChannel) met zijn codec, poort en protocol. ICE-kandidaten bevatten foundation (identificatie voor groepering), priority, IP-adres, poort, type (host, srflx, relay) en protocol (UDP, TCP). Elke candidate bevat ook het attribuut ufrag (username fragment) dat het verbindt met een specifiek ICE-proces.
Trickle ICE versnelt het opzetten van een WebRTC-verbinding aanzienlijk. In plaats van te wachten op de volledige verzameling van alle ICE-kandidaten (wat 2–10 seconden kan duren in complexe netwerken), wordt elke kandidaat onmiddellijk na ontdekking naar de Signaling Server gestuurd. De externe peer ontvangt de kandidaat en begint onmiddellijk met het testen van de verbinding via het ICE-framework. Dit verkort de verbindingstijd tot 500–1500 ms in de meeste gevallen.
Veelgestelde vragen
Signaling Server — is de “coördinator” vóór een gesprek. Het helpt twee apparaten elkaar te vinden en af te spreken hoe ze zullen communiceren. Nadat de apparaten elkaar hebben “lerend kennen” en overeenstemming hebben bereikt, is de server niet meer nodig — ze communiceren rechtstreeks.
WebRTC definieert het signaleringsprotocol niet, zodat ontwikkelaars het meest geschikte transport kunnen kiezen. De browser heeft geen ingebouwd mechanisme voor het detecteren van andere gebruikers — deze taak wordt opgelost door de Signaling Server. Deze fungeert als “postbode” en stuurt uitnodigingen en verbindingsinstellingen tussen deelnemers aan een gesprek.
WebSocket — de optimale keuze voor de meeste webapplicaties: full-duplex, native ondersteund door browsers, eenvoudig te implementeren. Voor integratie met bestaande VoIP-infrastructuur kiest u SIP. Voor chat-applicaties met rijke functionaliteit — XMPP. Voor IoT-scenario's — MQTT.
Voor het schalen van Signaling Server gebruikt u horizontaal schalen met synchronisatie via Redis Pub/Sub of Kafka. Elke serverinstantie verwerkt zijn eigen deel van de WebSocket-verbindingen en voor inter-server routering van berichten wordt een gemeenschappelijke gegevensbus gebruikt. Deze aanpak maakt het mogelijk miljoenen gelijktijdige signaleringssessies te verwerken.
Signaling Server is alleen cruciaal in de fase van het opzetten van de verbinding. Als de server tijdelijk niet beschikbaar is, gaan actieve WebRTC-gesprekken door — mediaverkeer gaat rechtstreeks tussen peers. Het probleem doet zich alleen voor bij het proberen een nieuwe verbinding op te zetten. Gebruik voor betrouwbaarheid serverclustering en reserve-signaleringskanalen.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook