Signaling Server — est un composant serveur de l'infrastructure WebRTC qui facilite l'échange de métadonnées entre les pairs pour établir et terminer une connexion. Contrairement au trafic multimédia, la signalisation peut être transmise via n'importe quel protocole — WebSocket, HTTP, XMPP ou SIP. Selon MDN Web Docs, 2024, la signalisation est un composant obligatoire de toute application WebRTC, car le protocole ne définit pas de méthode spécifique pour échanger des messages de signalisation.
Points clés
Signaling Server — est un service réseau responsable de la coordination du processus d'établissement d'une connexion WebRTC entre deux ou plusieurs pairs. Il ne transmet pas de données multimédia (audio, vidéo, données DataChannel), mais uniquement les informations de contrôle nécessaires à la découverte des pairs et à la négociation des paramètres de connexion. Après l'établissement réussi d'un canal P2P, le Signaling Server peut ne plus être nécessaire, mais dans certaines architectures, il reste pour l'échange ultérieur de signaux (par exemple, fin d'appel, ajout de participants).
L'architecture de signalisation comprend trois composants : Signaling Server, Signal Channel (protocole de transport entre le client et le serveur) et l'API client (généralement intégrée dans la pile WebRTC du navigateur). La spécification WebRTC (W3C, 2024) ne standardise intentionnellement pas le protocole de signalisation — les développeurs peuvent choisir n'importe quel transport adapté à leur application. Cette approche flexible permet d'utiliser WebSocket pour les applications web, XMPP pour les systèmes de chat ou SIP pour l'intégration avec l'infrastructure de télécommunications.
Avant d'établir une connexion WebRTC, les pairs doivent échanger trois types de messages : les descriptions de session (offer et answer), les candidats ICE et les informations de fin/modification de session. Le Signaling Server route ces messages entre les pairs en utilisant des identifiants de salle ou d'utilisateur pour l'adressage. Le modèle standard consiste à créer une “salle” où deux participants se connectent, et le serveur relaie les messages de chaque participant uniquement à son interlocuteur.
Signaling Server implémente le protocole typique d'établissement de connexion WebRTC suivant. Les pairs se connectent au serveur via WebSocket (ou un autre transport) et s'enregistrent dans une salle. Le pair A (l'initiateur) crée une offre (description SDP du flux multimédia sortant) via RTCPeerConnection.createOffer(), la définit comme description locale et l'envoie au Signaling Server. Le serveur relaie l'offre au pair B. Le pair B reçoit l'offre, la définit comme description distante, crée une réponse via createAnswer(), la définit comme description locale et la renvoie via le serveur. Ce processus est appelé SDP Offer/Answer.
En parallèle de l'échange SDP, chaque pair collecte des candidats ICE (host, srflx, relay) et les envoie via le Signaling Server à l'autre pair. Le pair distant ajoute les candidats reçus via RTCPeerConnection.addIceCandidate(). Le processus ICE teste toutes les combinaisons de candidats pour trouver un chemin fonctionnel. Une fois qu'un chemin fonctionnel est trouvé (généralement en 1 à 5 secondes), le trafic multimédia commence à circuler directement entre les pairs, et le Signaling Server ne participe plus à la transmission des données — son rôle est terminé jusqu'au prochain événement de contrôle (fin d'appel, changement de qualité du flux).
Pour l'adressage des messages, le Signaling Server utilise un mécanisme de salles (rooms) ou de canaux. Chaque nouvelle session WebRTC crée une salle unique avec un identifiant (généralement UUID). L'initiateur crée la salle et attend la connexion du second pair. Le second pair rejoint la salle en utilisant l'ID reçu via un canal externe (par exemple, un lien d'invitation). Le serveur maintient une carte des salles, où chaque ID correspond à une liste de clients connectés. Lorsque le nombre de participants atteint deux, le serveur commence à relayer les messages de signalisation entre eux.
Signaling Server peut utiliser différents protocoles de transport, chacun avec ses propres avantages et inconvénients. Le choix du protocole dépend du type d'application, des contraintes d'infrastructure et des exigences de compatibilité. Voici les protocoles les plus courants et leurs caractéristiques.
| Protocole | Transport | Avantages | Inconvénients |
|---|---|---|---|
| WebSocket | TCP | Full-duplex, faible latence, intégré aux navigateurs | Complexité de passage à l'échelle, blocage proxy |
| HTTP/SSE | TCP | Compatible avec toute infrastructure, simple à implémenter | Unidirectionnel uniquement (serveur-client), nécessite du polling |
| XMPP | TCP | Standardisé, support d'authentification, extensible | Excessif pour des scénarios simples, surcharge XML |
| SIP | UDP/TCP | Intégration avec l'infrastructure VoIP et téléphonique | Complexe, non natif pour les navigateurs |
| MQTT | TCP | Léger, fonctionne dans les environnements IoT, publish/subscribe | Nécessite un courtier, latence supplémentaire |
WebSocket est le protocole le plus populaire pour Signaling Server dans les applications web. Il fournit une communication full-duplex, importante pour l'échange asynchrone de candidats SDP et ICE, et est nativement supporté par tous les navigateurs modernes via l'API WebSocket. Les implémentations serveur WebSocket sont disponibles sur toutes les plateformes populaires (Node.js, Python, Java, Go). Pour les applications avec des millions d'utilisateurs, des solutions WebSocket évolutives basées sur Redis Pub/Sub ou Kafka sont utilisées pour synchroniser les instances de Signaling Server.
Examinons une implémentation simple de Signaling Server en Node.js utilisant la bibliothèque ws (WebSocket) et le serveur HTTP intégré. Le serveur prend en charge l'enregistrement des utilisateurs, la création de salles et le relais de messages entre les participants.
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);
}
Ce Signaling Server implémente les fonctionnalités de base : connexion à une salle, relais de messages WebRTC (offer, answer, ice-candidate) entre deux pairs et gestion des déconnexions. Le serveur utilise une Map pour stocker les salles avec les clients WebSocket connectés. La fonction relayToPeer envoie un message à tous les participants de la salle sauf l'expéditeur. Pour la production, vous devrez ajouter la validation des types de messages, la gestion des erreurs d'analyse JSON et un mécanisme heartbeat pour détecter les connexions interrompues.
Côté client, le Signaling Server est intégré via l'API WebSocket du navigateur. Le client établit une connexion avec le serveur, envoie une demande pour rejoindre une salle, puis traite les messages WebRTC entrants en les transmettant à RTCPeerConnection via setRemoteDescription() et addIceCandidate(). Le code client envoie également ses propres candidats SDP et ICE au serveur, obtenus de RTCPeerConnection via l'événement onicecandidate et après la création de l'offre/réponse.
Signaling Server transmet deux types principaux de métadonnées : SDP (Session Description Protocol) et les candidats ICE. SDP décrit les paramètres du flux multimédia — codecs, fréquence d'échantillonnage, nombre de canaux, direction de transmission (sendrecv, sendonly, recvonly, inactive). Les candidats ICE contiennent des adresses réseau (locales, obtenues de STUN, relay de TURN) par lesquelles un pair peut être joint pour la connexion.
SDP est présenté dans un format texte contenant des sections de session et de média. La partie session décrit les paramètres généraux (ID de session, version, nom), tandis que les sections média décrivent chaque flux multimédia (audio, vidéo, DataChannel) avec son codec, son port et son protocole. Les candidats ICE contiennent foundation (identifiant de regroupement), priorité, adresse IP, port, type (host, srflx, relay) et protocole (UDP, TCP). Chaque candidat inclut également un attribut ufrag (fragment de nom d'utilisateur) qui le lie à un processus ICE spécifique.
Trickle ICE accélère considérablement l'établissement de la connexion WebRTC. Au lieu d'attendre la collecte complète de tous les candidats ICE (qui peut prendre 2 à 10 secondes dans les réseaux complexes), chaque candidat est envoyé au Signaling Server immédiatement après sa découverte. Le pair distant reçoit le candidat et commence immédiatement le test de connexion via le framework ICE. Cela réduit le temps d'établissement de la connexion à 500–1500 ms dans la plupart des cas.
Questions fréquentes
Signaling Server — est le “coordinateur” avant un appel. Il aide deux appareils à se trouver et à se mettre d'accord sur la façon dont ils communiqueront. Une fois que les appareils se sont “rencontrés” et ont accepté, le serveur n'est plus nécessaire — ils communiquent directement.
WebRTC ne définit pas de protocole de signalisation afin que les développeurs puissent choisir le transport le plus approprié. Le navigateur n'a pas de mécanisme intégré pour découvrir d'autres utilisateurs — cette tâche est effectuée par le Signaling Server. Il agit comme un “facteur”, délivrant les invitations et les paramètres de connexion entre les participants à l'appel.
WebSocket — est le choix optimal pour la plupart des applications web : full-duplex, nativement supporté par les navigateurs et simple à implémenter. Pour l'intégration avec une infrastructure VoIP existante, choisissez SIP. Pour les applications de chat riches en fonctionnalités, utilisez XMPP. Pour les scénarios IoT, utilisez MQTT.
Pour passer à l'échelle un Signaling Server, utilisez la mise à l'échelle horizontale avec synchronisation via Redis Pub/Sub ou Kafka. Chaque instance de serveur gère sa part des connexions WebSocket, et un bus de données commun est utilisé pour le routage des messages entre serveurs. Cette approche permet de gérer des millions de sessions de signalisation simultanées.
Le Signaling Server est critique uniquement pendant la phase d'établissement de la connexion. Si le serveur devient temporairement indisponible, les appels WebRTC actifs continuent — le trafic multimédia circule directement entre les pairs. Le problème survient uniquement lors de la tentative d'établissement d'une nouvelle connexion. Pour la fiabilité, utilisez le clustering de serveurs et des canaux de signalisation de secours.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi