Enviar dados entre dois navegadores para comunicação, jogos ou transferência de arquivos pode ser um processo bastante complicado. É necessário configurar e pagar por um servidor para transmitir dados e talvez dimensionar isso para vários data centers. Nesse cenário, há a possibilidade de latência alta e é difícil manter os dados privados.
Esses problemas podem ser aliviados usando a API RTCDataChannel
do WebRTC para transferir dados diretamente de um peer para outro. Este artigo aborda os conceitos básicos de como configurar e usar canais de dados, além dos casos de uso comuns na Web.
Por que outro canal de dados?
Temos WebSocket, AJAX e Eventos enviados pelo servidor. Por que precisamos de outro canal de comunicação? O WebSocket é bidirecional, mas todas essas tecnologias são projetadas para comunicação com ou de um servidor.
O RTCDataChannel
usa uma abordagem diferente:
- Ele funciona com a API
RTCPeerConnection
, que permite a conectividade ponto a ponto. Isso pode resultar em menor latência, sem servidor intermediário e com menos "saltos". - O
RTCDataChannel
usa o Stream Control Transmission Protocol (SCTP), permitindo a configuração de entrega semântica fora de ordem e a retransmissão.
O RTCDataChannel
já está disponível com suporte ao SCTP no Google Chrome, Opera e Firefox para computador e Android.
Uma ressalva: sinalização, STUN e TURN
O WebRTC permite a comunicação ponto a ponto, mas ainda precisa de servidores para sinalizar a troca de mídia e metadados de rede para inicializar uma conexão ponto a ponto.
O WebRTC lida com NATs e firewalls com:
- O framework ICE para estabelecer o melhor caminho de rede possível entre pares.
- Servidores STUN para determinar um IP e uma porta acessíveis publicamente para cada peer.
- Servidores TURN, se a conexão direta falhar e o retransmissão de dados for necessária.
Para mais informações sobre como o WebRTC funciona com servidores para sinalização e rede, consulte WebRTC no mundo real: STUN, TURN e sinalização.
Os recursos
A API RTCDataChannel
oferece suporte a um conjunto flexível de tipos de dados. A API foi projetada para imitar exatamente o WebSocket, e RTCDataChannel
oferece suporte a strings e a alguns dos tipos binários em JavaScript, como Blob, ArrayBuffer e ArrayBufferView. Esses tipos podem ser úteis ao trabalhar com transferência de arquivos e jogos multijogador.
O RTCDataChannel
pode funcionar no modo não confiável e não ordenado (análogo ao protocolo de datagramas do usuário ou UDP), no modo confiável e ordenado (análogo ao protocolo de controle de transmissão ou TCP) e nos modos parcialmente confiáveis:
- O modo confiável e ordenado garante a transmissão de mensagens e a ordem em que elas são entregues. Isso leva a uma sobrecarga extra, o que pode tornar esse modo mais lento.
- O modo não confiável e não ordenado não garante que todas as mensagens cheguem ao destinatário nem a ordem em que elas chegam. Isso remove a sobrecarga, permitindo que esse modo funcione muito mais rápido.
- O modo de confiabilidade parcial garante a transmissão da mensagem sob uma condição específica, como um tempo limite de retransmissão ou uma quantidade máxima de retransmissões. A ordem das mensagens também é configurável.
O desempenho dos dois primeiros modos é praticamente o mesmo quando não há perdas de pacotes. No entanto, no modo confiável e ordenado, um pacote perdido faz com que outros pacotes sejam bloqueados atrás dele, e o pacote perdido pode estar desatualizado no momento em que é retransmitido e chega. É possível usar vários canais de dados no mesmo app, cada um com semânticas confiáveis ou não confiáveis.
Confira uma tabela útil de High Performance Browser Networking (em inglês) de Ilya Grigorik:
TCP | UDP | SCTP | |
Confiabilidade | Confiável | não confiáveis | Configurável |
Entrega | Pedido concluído | Desordenado | Configurável |
Transmissão | Orientado a bytes | Orientado a mensagens | Orientado a mensagens |
Controle de fluxo | Sim | Não | Sim |
Controle de congestionamento | Sim | Não | Sim |
A seguir, você vai aprender a configurar RTCDataChannel
para usar o modo confiável e ordenado ou não confiável e não ordenado.
Como configurar canais de dados
Há várias demonstrações simples de RTCDataChannel
on-line:
Nesses exemplos, o navegador faz uma conexão de peer com ele mesmo, cria um canal de dados e envia uma mensagem pela conexão de peer. Em seguida, ele cria um canal de dados e envia a mensagem pela conexão do par. Por fim, sua mensagem aparece na caixa do outro lado da página.
O código para começar é curto:
const peerConnection = new RTCPeerConnection();
// Establish your peer connection using your signaling channel here
const dataChannel =
peerConnection.createDataChannel("myLabel", dataChannelOptions);
dataChannel.onerror = (error) => {
console.log("Data Channel Error:", error);
};
dataChannel.onmessage = (event) => {
console.log("Got Data Channel Message:", event.data);
};
dataChannel.onopen = () => {
dataChannel.send("Hello World!");
};
dataChannel.onclose = () => {
console.log("The Data Channel is Closed");
};
O objeto dataChannel
é criado a partir de uma conexão de peer já estabelecida. Ele pode ser criado antes ou depois da sinalização. Em seguida, você transmite um rótulo para distinguir esse canal de outros e um conjunto de configurações opcionais:
const dataChannelOptions = {
ordered: false, // do not guarantee order
maxPacketLifeTime: 3000, // in milliseconds
};
Também é possível adicionar uma opção maxRetransmits
(o número de tentativas antes da falha), mas você só pode especificar maxRetransmits ou maxPacketLifeTime, não os dois. Para a semântica UDP, defina maxRetransmits
como 0
e ordered
como false
. Para mais informações, consulte estes RFCs do IETF: Stream Control Transmission Protocol e Stream Control Transmission Protocol Partial Reliability Extension.
ordered
: se o canal de dados precisa garantir a ordem ou nãomaxPacketLifeTime
: o tempo máximo para tentar retransmitir uma mensagem com falhamaxRetransmits
: o número máximo de vezes que uma mensagem com falha pode ser retransmitidaprotocol
: permite que um subprotocolo seja usado, o que fornece metainformações para o appnegotiated
: se definido como "true", remove a configuração automática de um canal de dados no outro peer, oferecendo sua própria maneira de criar um canal de dados com o mesmo ID do outro lado.id
: permite fornecer seu próprio ID para o canal, que só pode ser usado comnegotiated
definido comotrue
.
As únicas opções que a maioria das pessoas precisa usar são as três primeiras: ordered
, maxPacketLifeTime
e maxRetransmits
. Com o SCTP (que agora é usado por todos os navegadores com suporte ao WebRTC), a confiabilidade e a ordem são verdadeiras por padrão. Faz sentido usar a confiabilidade não confiável e não ordenada se você quiser ter controle total da camada do app, mas, na maioria dos casos, a confiabilidade parcial é útil.
Assim como no WebSocket, o RTCDataChannel
dispara eventos quando uma conexão é estabelecida, encerrada ou apresenta erros e quando recebe uma mensagem do outro peer.
É seguro?
A criptografia é obrigatória para todos os componentes do WebRTC. Com RTCDataChannel
, todos os dados são protegidos com Datagram Transport Layer Security (DTLS). O DTLS é um derivado do SSL, o que significa que seus dados serão tão seguros quanto o uso de qualquer conexão padrão baseada em SSL. O DTLS é padronizado e integrado a todos os navegadores compatíveis com o WebRTC. Para mais informações, consulte o wiki do Wireshark.
Mude sua forma de pensar sobre dados
O processamento de grandes quantidades de dados pode ser um problema em JavaScript. Como apontaram os desenvolvedores do Sharefest, isso exigiu uma nova forma de pensar sobre os dados. Se você estiver transferindo um arquivo maior do que a quantidade de memória disponível, terá que pensar em novas maneiras de salvar essas informações. É aqui que entram em ação tecnologias como a API FileSystem, como você vai ver a seguir.
Criar um app de compartilhamento de arquivos
Agora é possível criar um app da Web que compartilha arquivos no navegador com RTCDataChannel
. Criar em cima de RTCDataChannel
significa que os dados de arquivo transferidos são criptografados e não tocam os servidores de um provedor de app. Essa funcionalidade, combinada com a possibilidade de se conectar a vários clientes para um compartilhamento mais rápido, faz do compartilhamento de arquivos do WebRTC um candidato forte para a Web.
Várias etapas são necessárias para fazer uma transferência:
- Leia um arquivo em JavaScript usando a API File.
- Estabeleça uma conexão ponto a ponto entre clientes com
RTCPeerConnection
. - Crie um canal de dados entre clientes com
RTCDataChannel
.
Há vários pontos a serem considerados ao tentar enviar arquivos por RTCDataChannel
:
- Tamanho do arquivo:se o tamanho do arquivo for razoavelmente pequeno e puder ser armazenado e carregado como um Blob, você poderá carregar na memória usando a API File e enviar o arquivo por um canal confiável (mas lembre-se de que os navegadores impõem limites ao tamanho máximo de transferência). À medida que o tamanho do arquivo aumenta, as coisas ficam mais complicadas. Quando um mecanismo de divisão é necessário, os blocos de arquivos são carregados e enviados para outro peer, acompanhados de metadados
chunkID
para que o peer possa reconhecê-los. Nesse caso, você também precisa salvar os fragmentos primeiro no armazenamento off-line (por exemplo, usando a API FileSystem) e no disco do usuário somente quando tiver o arquivo completo. - Tamanho do bloco:são os menores "átomos" de dados do app. O agrupamento é necessário porque atualmente há um limite de tamanho de envio, mas isso será corrigido em uma versão futura dos canais de dados. A recomendação atual para o tamanho máximo do fragmento é de 64 KiB.
Depois que o arquivo é totalmente transferido para o outro lado, ele pode ser transferido usando uma tag de âncora:
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
Esses apps de compartilhamento de arquivos no PubShare e no GitHub usam essa técnica. Ambos são de código aberto e fornecem uma boa base para um app de compartilhamento de arquivos baseado em RTCDataChannel
.
O que você pode fazer?
O RTCDataChannel
abre portas para novas maneiras de criar apps para compartilhamento de arquivos, jogos multijogador e entrega de conteúdo.
- Compartilhamento de arquivos ponto a ponto, conforme descrito anteriormente
- Jogos multiplayer combinados com outras tecnologias, como o WebGL, como visto no BananaBread do Mozilla
- O fornecimento de conteúdo está sendo reinventado pelo PeerCDN, um framework que entrega recursos da Web por meio de comunicação de dados ponto a ponto
Mudar a forma de criar apps
Agora você pode oferecer apps mais interativos usando conexões de alto desempenho e baixa latência com RTCDataChannel
. Frameworks, como o PeerJS e o SDK do PubNub WebRTC, facilitam a implementação do RTCDataChannel
, e a API agora tem amplo suporte em várias plataformas.
O advento do RTCDataChannel
pode mudar a forma como você pensa sobre a transferência de dados no navegador.