Configurar um serviço de sinalização para troca de mensagens

event 25 de outubro de 2018 às 1:04 am

O que você vai aprender

Nesta etapa, você descobrirá como:

  • Usar o npm para instalar dependências do projeto, conforme especificado em package.json.
  • Executar um servidor Node.js e usar o node-static para fornecer arquivos estáticos.
  • Configurar um serviço de mensagens  no Node.js usando Socket.IO.
  • Usar isso para criar ‘salas’ e trocar mensagens.

Uma versão completa dessa etapa está na pasta step-04.

Conceitos

Para configurar e manter uma chamada WebRTC, os clientes WebRTC (pares) precisam trocar metadados:

Para configurar e manter uma chamada WebRTC, os clientes (pontos) precisam trocar metadados:

  • Candidato (rede) informações.
  • Oferecer e responder mensagens fornecendo informações sobre mídia, como resolução e codecs.

Em outras palavras, uma troca de metadados é necessária antes da que o fluxo de áudio, vídeo, ou dados ponto-a-ponto possa ocorrer. Esse processo é chamado de sinalização.

Nas etapas anteriores, o remetente e receptor do RTCPeerConnection são objetos na mesma página, então ‘sinalização’ é simples uma questão de passar metadados entre objetos.

Em uma aplicação do mundo real, o remetente e o receptor RTCPeerConnections são executados em páginas da web em dispositivos diferentes, e você precisa de uma maneira de comunicar os metadados.

Para isso você usa um servidor de sinalização: um servidor que pode passar mensagens entre os clientes (pontos) WebRTC. As mensagens reais são de texto simples: objetos JavaScript com string.

Pré-requisito: Instalar o Node.js

Para executar as próximas etapas desse codelab (pastas step-04 a step-06) você precisará executar um servidor localhost usando Node.js.

Você pode baixar e instalar o Node.js por este link ou através do seu  gerenciador de pacotes preferido.

Uma vez instalado, você será capaz de importar as dependências requeridas para as próximas etapas (execute npm install), bem como executar um pequeno servidor localhost para executar o codelab (execute node index.js). Esses comandos serão indicados posteriormente, quando forem necessários.

Sobre o Aplicativo

O WebRTC usa uma API JavaScript do lado do cliente, mas para o uso no mundo real  também requer um servidor de sinalização (mensagem), bem como servidores STUN e TURN. Você pode encontrar mais aqui.

Nessa etapa você criará um servidor de sinalização Node.js simples, usando o modulo Socket.io do Node.js e uma biblioteca JavaScript para sistema de mensagens.  A experiência com o Node.js e o Socket.IO será útil, mas não crucial; os componentes do sistema de mensagens são muito simples.

Escolhendo o servidor de sinalização certo. Este codelab usa o Socket.IO para um servidor de sinalização. O design do Socket.io torna simples a construir um serviço de troca de mensagens, e o Socket.io é adequado para apreender sobre sinalização WebRTC, porque ele é construído com o conceito de ‘salas’. No entanto, para um serviço em produção, existem alternativas melhores. Consulte como selecionar um protocolo de sinalização para seu próximo projeto WebRTC.

Neste Exemplo, o servidor (a aplicação em Node.js) é implementado no index.js , e o cliente que roda nele (o app web) está implementado no index.html.

A aplicação Node.js nesta etapa tem duas tarefas.

Primeira, ele atua com retransmissor de mensagem:

socket.on('message', function (message) {
  log('Got message: ', message);
  socket.broadcast.emit('message', message);
});

Segundo, ele gerencia as ‘salas’ de chat de video WebRTC:

if (numClients === 0) {
  socket.join(room);
  socket.emit('created', room, socket.id);
} else if (numClients === 1) {
  socket.join(room);
  socket.emit('joined', room, socket.id);
  io.sockets.in(room).emit('ready');
} else { // max two clients
  socket.emit('full', room);
}

Nossa simples aplicação em WebRTC, permitirá que no máximo dois pontos compartilhem uma sala.

HTML & JavaScript

Atualizando o index.html então fica assim:

<!DOCTYPE html>
<html>
<head>
  <title>Realtime communication with WebRTC</title>
  <link rel="stylesheet" href="css/main.css" />
</head>
<body>
  <h1>Realtime communication with WebRTC</h1>
  <script src="/socket.io/socket.io.js"></script>
  <script src="js/main.js"></script>
</body>
</html>

Você não vai ver nada na sua página nesta etapa: todo o registro é feito no console do navegador. (Para ver o console no Chrome, precione Ctrl-Shift-J, ou Command-Option-j se você estiver em um Mac.)

Reescreva o js/mainjs como a seguir:

'use strict';

var isInitiator;

window.room = prompt("Enter room name:");

var socket = io.connect();

if (room !== "") {
  console.log('Message from client: Asking to join room ' + room);
  socket.emit('create or join', room);
}

socket.on('created', function(room, clientId) {
  isInitiator = true;
});

socket.on('full', function(room) {
  console.log('Message from client: Room ' + room + ' is full :^(');
});

socket.on('ipaddr', function(ipaddr) {
  console.log('Message from client: Server IP address is ' + ipaddr);
});

socket.on('joined', function(room, clientId) {
  isInitiator = false;
});

socket.on('log', function(array) {
  console.log.apply(console, array);
});

Configurando o Socket.IO para rodar no Node.js

No aquivo HTML, você pode ter visto que está usando um arquivo Socket.IO:

<script src="/socket.io/socket.io.js"></script>


No nível superior do seu diretório de trabalho, crie um arquivo denominado package.json com o seguinte conteúdo:

{
  "name": "webrtc-codelab",
  "version": "0.0.1",
  "description": "WebRTC codelab",
  "dependencies": {
    "node-static": "^0.7.10",
    "socket.io": "^1.2.0"
  }
}

Este é um arquivo do aplicativo que informa ao Gerenciador de Pacotes do Node (npm) quais são as dependências do projeto instalar.

Para instalar as dependências (como a /socket.io/socket.io.js), execute a linha de comando a seguir no seu terminal, no seu diretório de trabalho:

Você deve ser um log de instalação com algo assim:

Como você pode ver, o npm instalou as dependências definidas no package.json.

Crie um novo arquivo index.js no nível superior do seu diretório de trabalho (não no diretório js) e adicione o código a seguir :

'use strict';

var os = require('os');
var nodeStatic = require('node-static');
var http = require('http');
var socketIO = require('socket.io');

var fileServer = new(nodeStatic.Server)();
var app = http.createServer(function(req, res) {
  fileServer.serve(req, res);
}).listen(8080);

var io = socketIO.listen(app);
io.sockets.on('connection', function(socket) {

  // convenience function to log server messages on the client
  function log() {
    var array = ['Message from server:'];
    array.push.apply(array, arguments);
    socket.emit('log', array);
  }

  socket.on('message', function(message) {
    log('Client said: ', message);
    // for a real app, would be room-only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', function(room) {
    log('Received request to create or join room ' + room);

    var clientsInRoom = io.sockets.adapter.rooms[room];
    var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;

    log('Room ' + room + ' now has ' + numClients + ' client(s)');

    if (numClients === 0) {
      socket.join(room);
      log('Client ID ' + socket.id + ' created room ' + room);
      socket.emit('created', room, socket.id);

    } else if (numClients === 1) {
      log('Client ID ' + socket.id + ' joined room ' + room);
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room, socket.id);
      io.sockets.in(room).emit('ready');
    } else { // max two clients
      socket.emit('full', room);
    }
  });

  socket.on('ipaddr', function() {
    var ifaces = os.networkInterfaces();
    for (var dev in ifaces) {
      ifaces[dev].forEach(function(details) {
        if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
          socket.emit('ipaddr', details.address);
        }
      });
    }
  });

});

No terminal de linha de comando, execute o comando a seguir no diretório de trabalho:

node index.js

No seu navegador, abra localhost:8080.

Cada vez que você abre está URL, você será solicitado a inserir um nome de sala. Para entrar na mesma sala, escolha o mesmo nome de sala todas as vezes, como ‘foo’.

Abra uma nova página, e abra localhost:8080 novamente. Escolha o mesmo nome de sala.

Abra localhost:8080 em uma terceira aba ou janela. Escolha o mesmo nome de sala novamente.

Verifique o console em cada uma das abas: você pode ver o registro do JavaScript acima.

Pontos bônus

  1. Quais mecanismos alternativos de mensagens podem ser possíveis? Que problemas você pode encontrar ao usar o WebSocket ‘puro’?
  2. Que problemas podem estar envolvidos com o dimensionamento deste aplicativo? Você pode desenvolver um método para testar milhares ou milhões de solicitações de salas simultâneas?
  3. Este aplicativo usa um prompt JavaScript para obter o nome do quarto. Descubra uma maneira de obter o nome da sala a partir da URL. Por exemplo localhost: 8080/foo forneceria o nome da sala foo.

O que você aprendeu

Nessa etapa, você aprendeu como:

  • Usar o npm para instalar dependências do projeto, conforme especificado no package.json.
  • Executar um servidor Node.js para os arquivos estáticos do servidor.
  • Configurar um serviço de mensagem com o Node.js usando o socket.io.
  • Usar isso para criar ‘salas’ e trocar mensagens.

Uma versão completa dessa etapa está na pasta step-04.

Encontre mais

Próximo

Descubra como usar a sinalização para permitir que dois usuários façam uma conexão de ponto.

Deixe uma resposta

Formulário Respondeu!