quarta-feira, 20 de janeiro de 2016

Node.js - Socket.io Manual - Parte 2 - Salas e Namespaces

 

Salas e Namespaces

Esse conceito é muito importante no Socket.io pois nos possibilita criar namespaces para os sockets, ou seja, criando diferentes endpoints.

Este é um recurso útil para minimizar o número de recursos (conexões TCP) e a facilidade de separação entre os canais de comunicação (sockets).

Namespace Padrão

Chamamos o namespace padrão / e é ondes clientes do Socket.IO irão conectar por padrão, e aquele que o servidor escuta por padrão.

Este namespace é identificado por io.sockets ou simplesmente io:

// os dois seguintes irão emitir a todos os sockets ligados ao`/`

io.sockets.emit('oi', 'para todos'); 

io.emit('oi', 'para todos'); // forma curta 

Cada namespace emite um evento de conexão que recebe cada socket como parâmetro.

io.on('connection', function(socket){ 

  socket.on('disconnect', function(){ });

});

Namespaces personalizados

Para configurar um namespace personalizado, você pode chamar a função of no servidor:

var nsp = io.of('/meu-namespace'); 

nsp.on('connection', function(socket){ 

  console.log('alguém conectou');

});

nsp.emit('oi', 'para todos!'); 

No lado do cliente, você diz para o Socket.io conectar naquele namespace:

var socket = io('/meu-namespace'); 

Nota importante: O namespace é um detalhe de implementação do protocolo Socket.IO, e não está relacionada com a URL real do transporte, cujo padrão é /socket.io/....

Salas

Dentro de cada namespace, você também pode definir canais arbitrários que os sockets podem entrar e sair.

Entrando e saindo

Você pode entrar join para assinar o socket a um determinado canal:

io.on('connection', function(socket){ 

  socket.join('minha sala');

});

io.to('minha sala').emit('algum evento'): 

Para deixar um canal você pode chamar leave da mesma forma que o join.

Sala padrão

Cada Socket no Socket.io é identificado por um randômico e únido identificador Socket.io#id. Para nossa facilidade, cada socket automaticamente entra em uma sala identificada por esse id.

Desconectando

Após a desconexão, sockets chamam leave em todos os canais que ele fazia parte automaticamente

O envio de mensagens a partir do mundo exterior

Em alguns casos, você pode querer emitir eventos para sockets em Socket.IO de fora do contexto do seu processo do Socket.io.

Há várias maneiras de resolver este problema, como a implementação de seu próprio canal para enviar mensagens para o processo.

Para nossa sorte temos 2 módulos que facilitam isso:

·         socket.io-redis

·         socket.io-emitter

Ao implementar o Adapter do Redis:

var io = require('socket.io')(3000); 

var redis = require('socket.io-redis'); 

io.adapter(redis({ host: 'localhost', port: 6379 })); 

Pode então emitir mensagens de qualquer outro processo de qualquer canal:

var io = require('socket.io-emitter')(); 

setInterval(function(){ 

  io.emit('time', new Date);

}, 5000);

Estou em um lugar sem wifi esse estava no draft, depois atualizarei com as imagens com mais exemplos.

Node.js - Socket.io Manual - Parte 1


clip_image001[4]

Criando um chat

Criar um chat com socket.io é como se fosse um Hello World, além de ser altamente usado no mundo real, ainda é o primeiro exemplo que os desenvolvedores fazem, então mãos a obra.

Criando servidor web

Primeiramente vamos criar uma aplicação express bem simples, para isso vamos criar seu package.json, você pode usar o comando npm initpara isso e ele precisa ficar igual a esse:

{

  "name": "socket-chat-exemplo",

  "version": "0.0.1",

  "description": "Meu primeiro app em socket.io",

  "dependencies": {}

}

Depois disso instalamos o socket.io com --save para ele ser inserido nas dependencies do package.json.

npm i --save express 

Agora podemos criar o index.js contendo o Express para levantarmos um servidor http com gerenciamento de rotas, o index.js deverá ficar assim:

var app = require('express')(); 

var http = require('http').Server(app);

 

app.get('/', function(req, res){ 

  res.send('<h1>Hello world</h1>');

});

 

http.listen(3000, function(){ 

  console.log('servidor rodando em localhost:3000');

});

Depois disso você entra na URL localhost:3000 e verá um belo e grandeHello World. Agora vamos criar um index.html que será servido pelo Express para nosso front-end.

<!doctype html> 

<html> 

  <head>

    <title>Socket.IO chat</title>

    <style>

      * { margin: 0; padding: 0; box-sizing: border-box; }

      body { font: 13px Helvetica, Arial; }

      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }

      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }

      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }

      #messages { list-style-type: none; margin: 0; padding: 0; }

      #messages li { padding: 5px 10px; }

      #messages li:nth-child(odd) { background: #eee; }

    </style>

  </head>

  <body>

    <ul id="messages"></ul>

    <form action="">

      <input id="m" autocomplete="off" /><button>Send</button>

    </form>

  </body>

</html> 

E precisamos mudar nossa rota no Express para ela servir esse arquivo.

app.get('/', function(req, res){ 

  res.sendFile(__dirname + '/index.html');

});

image

Integrando o socket.io

Já criamos a nossa interface básica, agora precisamos instalar o socket.io o qual é dividido em 2 partes:

·         Um servidor que se integra ao servidor HTTP do Node.js: socket.io

·         Uma biblioteca que carregamos no navegador: socket.io-client

Para começarmos a integrar antes precisamos instalar ele localmente:

npm i --save socket.io 

Depois vamos modificar o index.js e deixá-lo assim:

var app = require('express')(); 

var http = require('http').Server(app); 

var io = require('socket.io')(http);

 

app.get('/', function(req, res){ 

  res.sendFile(__dirname + '/index.html');

});

 

io.on('connection', function(socket){ 

  console.log('um usuario conectou');

});

 

http.listen(3000, function(){ 

  console.log('servidor rodando em localhost:3000');

});

Vamos analisar as modificações:

var io = require('socket.io')(http); 

Aqui estamos importando o socket.io passando para seu módulo nosso servidor HTTP.

io.on('connection', function(socket){ 

  console.log('um usuario conectou');

});

E no código acima estamos usando a função on escutando o evento connectione recebendo o objeto socket via callback.

Depois disso precisamos integrar o socket.io no front-end, para isso vamos inserir o seguinte código no final, antes do </body>, do index.html:

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

<script> 

  var socket = io();

</script> 

Na chamada src="/socket.io/socket.io.js" vai carregar o socket.io-client que expõe uma global, io.

Na única linha do nosso script nós estamos

image

Você pode abrir mais abas e ver elas conectadas.

image

Cada socket também pode disparar o evento disconnect e para ouvirmos ele modificaremos nosso código para o seguinte:

io.on('connection', function(socket){ 

  console.log('um usuario conectou');

  socket.on('disconnect', function(){

    console.log('usuario desconectou');

  });

});

Perceba que o disconnect não está no io que é nosso servidor e sim emcada socket que chega no nosso servidor, por isso a função on está sendo chamada no socket.

Agora você pode atualizar um aba várias vezes e terá o seguinte resultado:

image

Emitindo eventos

A principal ideia por trás do Socket.io é que você possa enviar e receber qualquer evento e qualquer dado que você quiser. Você pode enviar qualquer objeto que possa ser convertido para JSON, dados binários também são suportados.

Vamos emitir um evento quando o usuário escrever uma mensagem, o servidor receberá um evento chamado chat message, porém para fazermos nosso exemplo mais fácil utilizaremos o jQuery e enviamos os dados quando emitimos o evento.

<script src="http://code.jquery.com/jquery-1.11.1.js"></script> 

<script> 

  var socket = io();

  $('form').submit(function(){

    var mensagem = $('#m').val();

    socket.emit('chat message', mensagem);

    $('#m').val('');

    return false;

  });

</script> 

O envio da mensagem se dá nessa linha socket.emit('chat message', $('#m').val());. Fácil perceber que a função emit é a responsável por emitirmos um evento que será recebido via socket no nosso servidor.

Depois só precisamos ouvir esse evento no servidor.

socket.on('chat message', function(msg){ 

  console.log('message: ' + msg);

});

Agora vamo testar nosso chat se está enviando a mensagem e o servidor está recebendo.


image

image

Agora vamos ouvir as mensagens do chat que veem do servidor para o cliente, para isso iremos usar a função on para escutar o evento chat message:

<script> 

  var socket = io();

  $('form').submit(function(){

    var mensagem = $('#m').val();

    socket.emit('chat message', mensagem);

    $('#m').val('');

    return false;

  });

  socket.on('chat message', function(msg){

    $('#messages').append($('<li>').text(msg));

  });

</script> 

Chamamos essa função fora do submit do jQuery já que precisamos que o socket esteja ouvindo mesmo antes do cliente enviar qualquer coisa.

Com isso já iniciamos um chat, mas para criarmos um chat com suas funcionalidades comuns com envio de mensagem direta ou em canais específicos precisaremos utilizar outros conceitos do Socket.io que iremos ver agora.

Mostrei nesse artigo o básico do Socket.io na prática, mas ele ainda tem muitas outras funcionalidades então aguarde as próximas partes.