O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Introdução às conexões de pares

Conexões de ponto é a parte das especificações do WebRTC que trata da conexão de dois aplicativos em computadores diferentes para se comunicar usando um protocolo ponto a ponto. A comunicação entre pares pode ser de vídeo, áudio ou dados binários arbitrários (para clientes que suportam a API RTCDataChannel ). Para descobrir como dois pares podem se conectar, os dois clientes precisam fornecer uma configuração do ICE Server. Este é um servidor STUN ou TURN, e sua função é fornecer candidatos a ICE para cada cliente, que é então transferido para o ponto remoto. Essa transferência de candidatos a ICE é comumente chamada de sinalização.

Sinalização

A especificação WebRTC inclui APIs para comunicação com um servidor ICE (Internet Connectivity Establishment), mas o componente de sinalização não faz parte dele. A sinalização é necessária para que dois pares compartilhem como devem se conectar. Geralmente, isso é resolvido por meio de uma API Web baseada em HTTP regular (ou seja, um serviço REST ou outro mecanismo RPC), em que os aplicativos Web podem retransmitir as informações necessárias antes que a conexão entre pares seja iniciada.

O trecho de código a seguir mostra como esse serviço de sinalização fictício pode ser usado para enviar e receber mensagens de forma assíncrona. Isso será usado nos exemplos restantes neste guia, quando necessário.

 // 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!');
 

A sinalização pode ser implementada de várias maneiras diferentes, e a especificação WebRTC não prefere nenhuma solução específica.

Iniciando conexões de pares

Cada conexão de mesmo nível é manipulada por um objeto RTCPeerConnection . O construtor para esta classe usa um único objeto RTCConfiguration como parâmetro. Este objeto define como a conexão de mesmo nível é configurada e deve conter informações sobre os servidores ICE a serem usados.

Depois que o RTCPeerConnection é criado, precisamos criar uma oferta ou resposta SDP, dependendo de sermos o ponto de chamada ou o ponto de recebimento. Depois que a oferta ou resposta do SDP é criada, ela deve ser enviada ao ponto remoto por um canal diferente. A passagem de objetos SDP para pares remotos é chamada de sinalização e não é coberta pela especificação WebRTC.

Para iniciar a configuração da conexão de mesmo nível do lado que está chamando, criamos um objeto RTCPeerConnection e, em seguida, chamamos createOffer() para criar um objeto RTCSessionDescription . Esta descrição da sessão é definida como a descrição local usando setLocalDescription() e é enviada pelo canal de sinalização para o lado receptor. Também configuramos um ouvinte para o nosso canal de sinalização para quando uma resposta à nossa descrição de sessão oferecida é recebida do lado receptor.

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

No lado do recebimento, aguardamos uma oferta recebida antes de criarmos nossa instância RTCPeerConnection . Feito isso, definimos a oferta recebida usando setRemoteDescription() . Em seguida, chamamos createAnswer() para criar uma resposta para a oferta recebida. Esta resposta é definida como a descrição local usando setLocalDescription() e depois enviada para o lado que está chamando pelo nosso servidor de sinalização.

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

Depois que os dois pares definem as descrições de sessão local e remota, eles conhecem os recursos do ponto remoto. Isso não significa que a conexão entre os pares esteja pronta. Para que isso funcione, precisamos coletar os candidatos a ICE em cada par e transferir (pelo canal de sinalização) para o outro par.

Candidatos a ICE

Antes que dois pares possam se comunicar usando o WebRTC, eles precisam trocar informações de conectividade. Como as condições da rede podem variar dependendo de vários fatores, geralmente é usado um serviço externo para descobrir os possíveis candidatos à conexão com um par. Este serviço é chamado ICE e está usando um servidor STUN ou TURN. STUN é a sigla de Session Traversal Utilities for NAT, e geralmente é usado indiretamente na maioria dos aplicativos WebRTC.

TURN (Traversal Using Relay NAT) é a solução mais avançada que incorpora os protocolos STUN e a maioria dos serviços comerciais baseados no WebRTC usa um servidor TURN para estabelecer conexões entre pares. A API WebRTC suporta STUN e TURN diretamente, e é coletada sob o termo mais completo Estabelecimento de conectividade com a Internet. Ao criar uma conexão WebRTC, normalmente fornecemos um ou vários servidores ICE na configuração do objeto RTCPeerConnection .

Trickle ICE

Depois que um objeto RTCPeerConnection é criado, a estrutura subjacente usa os servidores ICE fornecidos para reunir candidatos ao estabelecimento de conectividade (candidatos a ICE). O evento icegatheringstatechange on RTCPeerConnection sinaliza em que estado a reunião do ICE é ( new , gathering ou complete ).

Embora seja possível que um par espere até que a coleta do ICE seja concluída, geralmente é muito mais eficiente usar uma técnica de "gotejamento" e transmitir cada candidato ao ICE ao par remoto à medida que for descoberto. Isso reduzirá significativamente o tempo de configuração da conectividade entre pares e permitirá que uma chamada de vídeo comece com menos atrasos.

Para reunir candidatos a ICE, basta adicionar um ouvinte para o evento icecandidate . O RTCPeerConnectionIceEvent emitido nesse ouvinte conterá a propriedade candidate que representa um novo candidato que deve ser enviado ao ponto remoto (consulte Sinalização).

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

Conexão estabelecida

Depois que os candidatos ao ICE estiverem sendo recebidos, devemos esperar que o estado de nossa conexão entre colegas acabe mudando para um estado conectado. Para detectar isso, adicionamos um ouvinte ao nosso RTCPeerConnection onde ouvimos eventos de RTCPeerConnection de connectionstatechange .

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

Documentação da API RTCPeerConnection