Premiers pas avec la connexion entre pairs

Les connexions de pairs sont la partie des spécifications WebRTC qui traite en connectant deux applications sur des ordinateurs différents pour communiquer à l'aide d'un protocole peer-to-peer. La communication entre pairs peut être vidéo, audio ou des données binaires arbitraires (pour les clients compatibles avec l'API RTCDataChannel). Dans Pour découvrir comment deux pairs peuvent communiquer, ils doivent tous les deux fournir un ICE Configuration du serveur. Il s'agit d'un serveur STUN ou d'un serveur TURN, et leur rôle est de fournir des candidats ICE à chaque client, qui sont ensuite transférés vers le pairs. Ce transfert de candidats ICE est communément appelé "signalement".

Serveur de signalement

La spécification WebRTC inclut des API de communication avec un ICE (Internet d'établissement de la connectivité), mais le composant de signalisation ne fait pas partie La signalisation est nécessaire pour que deux pairs puissent partager comment ils doivent se connecter. En général, ce problème est résolu à l'aide d'une API Web standard basée sur HTTP (une API REST ou un autre mécanisme RPC), où les applications Web peuvent relayer les avant d'établir la connexion au pair.

L'extrait de code suivant montre comment ce service de signalement fictif peut être utilisé pour envoyer et recevoir des messages de manière asynchrone. Il sera utilisé dans les autres exemples présentés dans ce guide si nécessaire.

// Set up an asynchronous communication channel that will be
// used during the peer connection setup
const signalingChannel = new SignalingChannel(remoteClientId);
signalingChannel.addEventListener('message', message => {
    // New message from remote client received
});

// Send an asynchronous message to the remote client
signalingChannel.send('Hello!');

La signalisation peut être implémentée de nombreuses façons différentes, spécification ne préfère aucune solution spécifique.

Établir des connexions d'appairage

Chaque connexion de pair est gérée par un objet RTCPeerConnection. Constructeur pour cette classe n'utilise qu'un seul objet RTCConfiguration comme paramètre. Ce définit la configuration de la connexion au pair et doit contenir des informations. sur les serveurs ICE à utiliser.

Une fois le RTCPeerConnection créé, nous devons créer une offre SDP ou réponse, selon que nous sommes le pair appelant ou le pair destinataire. Une fois que le fournisseur une offre ou une réponse, elle doit être envoyée au pair distant un autre canal. La transmission d’objets SDP à des pairs distants est appelée n'est pas couverte par la spécification WebRTC.

Pour lancer la configuration de la connexion au pair côté appelant, nous créons un RTCPeerConnection, puis appelez createOffer() pour créer un RTCSessionDescription. Cette description de session est définie comme la description à l'aide de setLocalDescription(), puis est envoyée par notre vers le côté récepteur. Nous configurons également un écouteur pour notre canal utilisé lorsque la réponse à la description de la session proposée est reçue de la part de côté récepteur.

async function makeCall() {
    const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]}
    const peerConnection = new RTCPeerConnection(configuration);
    signalingChannel.addEventListener('message', async message => {
        if (message.answer) {
            const remoteDesc = new RTCSessionDescription(message.answer);
            await peerConnection.setRemoteDescription(remoteDesc);
        }
    });
    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);
    signalingChannel.send({'offer': offer});
}

Du côté de la réception, nous attendons une offre entrante avant de créer notre Instance RTCPeerConnection. Une fois cela fait, nous définissons l'offre reçue à l'aide de setRemoteDescription() Ensuite, nous appelons createAnswer() pour créer une réponse à l'offre reçue. Cette réponse est définie comme description locale en utilisant setLocalDescription(), puis envoyé du côté appelant via notre signal Google Cloud.

const peerConnection = new RTCPeerConnection(configuration);
signalingChannel.addEventListener('message', async message => {
    if (message.offer) {
        peerConnection.setRemoteDescription(new RTCSessionDescription(message.offer));
        const answer = await peerConnection.createAnswer();
        await peerConnection.setLocalDescription(answer);
        signalingChannel.send({'answer': answer});
    }
});

Une fois que les deux pairs ont défini les descriptions des sessions locales et distantes, les capacités du pair distant. Cela ne signifie pas que la connexion entre les pairs est prêt. Pour que cela fonctionne, nous devons collecter l'ICES les candidats de chaque pair et le transférer (via le canal de signalement) à l'autre pairs.

Candidats ICE

Avant que deux pairs puissent communiquer à l'aide de WebRTC, ils doivent échanger des informations sur la connectivité. Les conditions du réseau peuvent varier en fonction un certain nombre de facteurs, un service externe est généralement utilisé pour découvrir les candidats possibles de se connecter à un pair. Ce service s'appelle ICE et en utilisant soit un serveur STUN, soit un serveur TURN. STUN est l'abréviation de Session Traversal. Utilitaires pour NAT, généralement utilisé indirectement dans la plupart des applications WebRTC.

TURN (Traversal Using Relay NAT) est la solution la plus avancée qui intègre les protocoles STUN et la plupart des services commerciaux basés sur WebRTC utilisent un serveur TURN permettant d'établir des connexions entre les pairs. L'API WebRTC est compatible avec STUN et TURN directement, et elles sont regroupées sous le terme plus complet Établissement de la connectivité. Lors de la création d'une connexion WebRTC, nous avons généralement fournir un ou plusieurs serveurs ICE dans la configuration RTCPeerConnection.

Glace glissante

Une fois qu'un objet RTCPeerConnection est créé, le framework sous-jacent utilise a fourni des serveurs ICE pour rassembler les candidats à l’établissement de la connectivité (ICE, candidats). L'événement icegatheringstatechange sur RTCPeerConnection signaux l'état de la collecte ICE (new, gathering ou complete) ;

Bien qu'il soit possible pour un pair d'attendre que la collecte ICE soit terminée, elle il est généralement beaucoup plus efficace d'utiliser un verglas technique et transmettre chaque candidat ICE au pair distant au fur et à mesure qu’il est découvert. Cela permettra de réduire considérablement le temps de configuration de la connectivité avec les pairs et autoriser l'accès aux vidéos appelez-nous pour vous lancer plus rapidement.

Pour rassembler des candidats ICE, il vous suffit d'ajouter un écouteur pour l'événement icecandidate. Le RTCPeerConnectionIceEvent émis sur cet écouteur contiendra Propriété candidate qui représente un nouveau candidat à envoyer à la pair distant (voir "Signalisation").

// Listen for local ICE candidates on the local RTCPeerConnection
peerConnection.addEventListener('icecandidate', event => {
    if (event.candidate) {
        signalingChannel.send({'new-ice-candidate': event.candidate});
    }
});

// Listen for remote ICE candidates and add them to the local RTCPeerConnection
signalingChannel.addEventListener('message', async message => {
    if (message.iceCandidate) {
        try {
            await peerConnection.addIceCandidate(message.iceCandidate);
        } catch (e) {
            console.error('Error adding received ice candidate', e);
        }
    }
});

Connexion établie

Une fois les candidats ICE reçus, nous devons nous attendre à voir l'État pour notre homologue connexion passera finalement à un état connecté. Pour le détecter, nous ajoutons écouteur sur notre RTCPeerConnection où nous écoutons connectionstatechange événements.

// Listen for connectionstatechange on the local RTCPeerConnection
peerConnection.addEventListener('connectionstatechange', event => {
    if (peerConnection.connectionState === 'connected') {
        // Peers connected!
    }
});

API RCPeerConnection documentation