As conexões de peering são parte das especificações do WebRTC que lida com
conectando dois aplicativos em computadores diferentes para que eles se comuniquem usando um
protocolo ponto a ponto. A comunicação entre pares pode ser de vídeo, áudio
dados binários arbitrários (para clientes com suporte à API RTCDataChannel
). Em
para descobrir como dois pares podem se conectar, ambos precisam fornecer um endereço de e-mail
Configuração do servidor. Esse é um servidor STUN ou TURN, e o papel dele é
para dar candidatos ICE a cada cliente, que depois são transferidos para a
peering. Essa transferência de candidatos ICE é chamada de sinalização.
Sinalização
A especificação WebRTC inclui APIs para a comunicação com uma instância de estabelecimento de conectividade), mas o componente de sinalização não faz parte reimplantá-lo. A sinalização é necessária para que dois colegas compartilhem como eles precisam se conectar. Geralmente, isso é resolvido com uma API Web normal baseada em HTTP (ou seja, uma API REST ou outro mecanismo de RPC) em que os aplicativos da Web podem retransmitir as antes que a conexão de peering seja iniciada.
O snippet de código a seguir mostra como esse serviço de sinalização fictícia pode ser usado para enviar e receber mensagens de forma assíncrona. Isso será usado no restante 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, e o WebRTC especificação não prefere uma solução específica.
Iniciar conexões de pares
Cada conexão de peering é processada por um objeto RTCPeerConnection
. O construtor
para essa classe usa um único objeto RTCConfiguration
como parâmetro. Isso
define como a conexão de peering é configurada e deve conter informações
sobre os servidores ICE a serem usados.
Depois que o RTCPeerConnection
for criado, precisamos criar uma oferta SDP ou
resposta, dependendo se somos o ponto de chamada ou o ponto de recebimento. Depois que o SDP
uma oferta ou resposta for criada, ela deve ser enviada ao terminal remoto por meio de um
um canal diferente. A transmissão de objetos SDP para pares remotos é chamada de sinalização e
não é coberto pela especificação WebRTC.
Para iniciar a configuração da conexão de peering no lado da chamada, criamos uma
objeto RTCPeerConnection
e, em seguida, chame createOffer()
para criar um
objeto RTCSessionDescription
. A descrição desta sessão está definida como local
usando setLocalDescription()
, que é enviada pela nossa sinalização
canal para o lado de destino. Também configuramos um listener para nossa
canal para quando receber uma resposta à descrição da sessão oferecida
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 destinatário, aguardamos uma oferta recebida antes de criar nosso
RTCPeerConnection
. Depois de fazer 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 enviados para o lado da chamada pela nossa sinalização
servidor.
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 definirem as descrições de sessão local e remota, conhecer os recursos do terminal remoto. Isso não significa que a conexão entre os pares está pronto. Para que isso funcione, precisamos coletar candidatos em cada grupo e transferem (pelo canal de sinalização) para os outros peering.
Candidatos ao ICE
Antes que dois pares possam se comunicar usando WebRTC, eles precisam trocar informações sobre conectividade. Como as condições da rede podem variar dependendo vários fatores, um serviço externo costuma ser usado para descobrir possíveis candidatos para se conectar com um colega. Esse serviço é chamado de ICE e é usando um servidor STUN ou TURN. STUN significa "travessia de sessão". Utilitários para NAT e geralmente é usado indiretamente na maioria dos aplicativos WebRTC.
O TURN (Traversal Using Relay NAT) é a solução mais avançada que incorpora
os protocolos STUN e a maioria dos serviços comerciais baseados em WebRTC usam um servidor TURN
para estabelecer conexões entre pares. A API WebRTC é compatível com STUN
e TURN diretamente, e estão reunidos sob o termo mais completo
Estabelecimento de conectividade. Ao criar uma conexão WebRTC, geralmente
que fornece um ou vários servidores ICE na configuração do
RTCPeerConnection
.
Gelo de gotejamento
Depois que um objeto RTCPeerConnection
é criado, o framework usa o
servidores ICE fornecidos para reunir candidatos para estabelecimento de conectividade (ICE
candidatos). O evento icegatheringstatechange
em RTCPeerConnection
indicadores
em que estado está a coleta de ICE (new
, gathering
ou complete
).
Embora seja possível que um par espere até que a coleta de ICE seja concluída, ela costuma ser muito mais eficiente usar um "gelo de gota" técnica e transmitem cada candidato da ICE ao par remoto à medida que eles são descobertos. Isso vai reduzir significativamente o tempo de configuração da conexão de peering e permitir que a para começar com menos atrasos.
Para reunir candidatos ICE, basta adicionar um listener para o evento icecandidate
.
O RTCPeerConnectionIceEvent
emitido nesse listener contém
propriedade candidate
que representa um novo candidato que precisa ser enviado ao
peering 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 ICE forem recebidos, devemos esperar o estado para nosso colega
vai mudar para o estado conectado. Para detectar isso, adicionamos um
listener para nossa RTCPeerConnection
, em que ouvimos connectionstatechange
.
eventos.
// Listen for connectionstatechange on the local RTCPeerConnection
peerConnection.addEventListener('connectionstatechange', event => {
if (peerConnection.connectionState === 'connected') {
// Peers connected!
}
});