Google is committed to advancing racial equity for Black communities. See how.
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Introduzione alle connessioni peer

Connessioni peer è la parte delle specifiche WebRTC che si occupa della connessione di due applicazioni su computer diversi per comunicare utilizzando un protocollo peer-to-peer. La comunicazione tra peer può essere video, audio o dati binari arbitrari (per i client che supportano l'API RTCDataChannel ). Per scoprire come possono connettersi due peer, entrambi i client devono fornire una configurazione di ICE Server. Questo è un server STUN o TURN e il loro ruolo è fornire candidati ICE a ciascun client che viene poi trasferito al peer remoto. Questo trasferimento di candidati ICE è comunemente chiamato segnalazione.

segnalazione

La specifica WebRTC include API per la comunicazione con un server ICE (Internet Connectivity Establishment), ma il componente di segnalazione non fa parte di esso. La segnalazione è necessaria affinché due peer condividano il modo in cui dovrebbero connettersi. In genere, ciò viene risolto tramite una normale API Web basata su HTTP (ovvero un servizio REST o un altro meccanismo RPC) in cui le applicazioni Web possono inoltrare le informazioni necessarie prima che venga avviata la connessione peer.

Il frammento di codice seguente mostra come utilizzare questo servizio di segnalazione fittizio per inviare e ricevere messaggi in modo asincrono. Questo sarà usato nei restanti esempi in questa guida dove necessario.

 // 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 segnalazione può essere implementata in molti modi diversi e la specifica WebRTC non preferisce alcuna soluzione specifica.

Avvio di connessioni peer

Ogni connessione peer è gestita da un oggetto RTCPeerConnection . Il costruttore per questa classe accetta un singolo oggetto RTCConfiguration come parametro. Questo oggetto definisce come è impostata la connessione peer e deve contenere informazioni sui server ICE da utilizzare.

Una volta creato RTCPeerConnection dobbiamo creare un'offerta o una risposta SDP, a seconda che siamo il peer chiamante o il peer ricevente. Una volta creata l'offerta o la risposta SDP, questa deve essere inviata al peer remoto attraverso un canale diverso. Il passaggio di oggetti SDP a peer remoti è chiamato segnalazione e non è coperto dalla specifica WebRTC.

Per avviare la configurazione della connessione peer dal lato chiamante, creiamo un oggetto RTCPeerConnection e quindi chiamiamo createOffer() per creare un oggetto RTCSessionDescription . Questa descrizione della sessione viene impostata come descrizione locale utilizzando setLocalDescription() e viene quindi inviata sul nostro canale di segnalazione al lato ricevente. Abbiamo anche creato un ascoltatore per il nostro canale di segnalazione per quando una risposta alla descrizione della nostra sessione offerta viene ricevuta dal lato ricevente.

 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});
}
 

Per quanto riguarda la ricezione, attendiamo un'offerta in arrivo prima di creare la nostra istanza RTCPeerConnection . Fatto ciò, impostiamo l'offerta ricevuta usando setRemoteDescription() . Successivamente, chiamiamo createAnswer() per creare una risposta all'offerta ricevuta. Questa risposta viene impostata come descrizione locale utilizzando setLocalDescription() e quindi inviata al lato chiamante sul nostro server di segnalazione.

 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});
    }
});
 

Una volta che i due peer hanno impostato le descrizioni delle sessioni locali e remote, conoscono le capacità del peer remoto. Ciò non significa che la connessione tra i peer sia pronta. Perché ciò funzioni, dobbiamo raccogliere i candidati ICE in ciascun peer e trasferirli (attraverso il canale di segnalazione) all'altro peer.

Candidati ICE

Prima che due peer possano comunicare con WebRTC, devono scambiarsi informazioni sulla connettività. Poiché le condizioni della rete possono variare in base a una serie di fattori, viene solitamente utilizzato un servizio esterno per scoprire i possibili candidati per la connessione a un peer. Questo servizio si chiama ICE e utilizza un server STUN o TURN. STUN è l'acronimo di Session Traversal Utilities per NAT e viene solitamente utilizzato indirettamente nella maggior parte delle applicazioni WebRTC.

TURN (Traversal Using Relay NAT) è la soluzione più avanzata che incorpora i protocolli STUN e la maggior parte dei servizi commerciali basati su WebRTC utilizza un server TURN per stabilire connessioni tra peer. L'API WebRTC supporta direttamente sia STUN che TURN, ed è raccolta sotto il termine più completo Stabilimento di connettività Internet. Quando si crea una connessione WebRTC, solitamente forniamo uno o più server ICE nella configurazione per l'oggetto RTCPeerConnection .

Trickle ICE

Una volta RTCPeerConnection un oggetto RTCPeerConnection , il framework sottostante utilizza i server ICE forniti per raccogliere i candidati per lo stabilimento di connettività (candidati ICE). L'evento icegatheringstatechange su RTCPeerConnection segnala in quale stato si trova la riunione ICE ( new , gathering o complete ).

Mentre è possibile per un peer attendere fino al completamento della raccolta ICE, di solito è molto più efficiente utilizzare una tecnica di "gocciolamento di ghiaccio" e trasmettere ogni candidato ICE al peer remoto non appena viene scoperto. Ciò ridurrà significativamente i tempi di configurazione della connettività peer e consentirà di avviare una videochiamata con meno ritardi.

Per raccogliere i candidati ICE, è sufficiente aggiungere un ascoltatore per l'evento icecandidate . RTCPeerConnectionIceEvent emesso su quel listener conterrà la proprietà candidate che rappresenta un nuovo candidato che dovrebbe essere inviato al peer remoto (Vedi Segnalazione).

 // 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);
        }
    }
});
 

Connessione stabilita

Una volta ricevuti i candidati ICE, dovremmo aspettarci che lo stato della nostra connessione peer alla fine cambierà in uno stato connesso. Per rilevarlo, aggiungiamo un listener al nostro RTCPeerConnection dove ascoltiamo gli eventi di cambio di connectionstatechange .

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

Documentazione API RTCPeerConnection