Ultimamente andei trabalhando no desenvolvimento do meu site pessoal para publicação do meu portifólio de projetos, com isso surgiu a necessidade de programar algo interessante para chamar atenção no meu site. Estudei os conceitos teóricos e práticos para implementar um módulo de estatísticas de visitantes, pelo qual apresenta em tempo real o número de visitantes online, e seu respectivo browser e sistema operacional.

Toda implementação foi utilizando o módulo Socket.IO do Node.js, que permite realizar comunicação bidirecional utilizando uma das APIs de transporte na seguinte ordem: WebSockets, FlashSockets, AJAX long polling, AJAX multipart streaming, Forever Iframe ou JSONP Polling. O motivo da ordem é garantir compatibilidade cross-browser.

Na prática o Socket.IO abre uma conexão com servidor pelo qual possibilita realizar troca de mensagens entre ambos sem a necessidade de dar um refresh na página, ou seja, sem a necessidade de solicitar uma nova request para o servidor. Com isso é possível explorar o conceito de real-time em uma aplicação, pelo qual basicamente o cliente envia uma mensagem e o servidor processa e responde via broadcast (para todos os clientes de conexão aberta com servidor) através de um long pooling de conexão.

Esse conceito é muito aplicado em aplicações de geração de relatórios em tempo real, chats, jogos multiplayer online, aplicações de interação em tempo real com diversos usuários (Google Docs, Facebook, Twitter são exemplo disso) e muito mais.

Abaixo apresentarei um simples exemplo de um contador de usuários online com atualização real-time:

// Servidor: app.js
// Instanciando os módulos HTTP, FS (File System) e Socket.io.
var http = require('http').createServer(index)
  , io = require('socket.io').listen(http)
  , fs = require('fs');

// Configurando a porta de listen do servidor.
http.listen(8080);

// Método de requisição para apresentar a página index.html.
function index(req, res){
  var page = __dirname + '/index.html';
  fs.readFile(page, function(err, data){
	  res.writeHead(200);
    res.end(data);	
  });
};
// Contador de visitas.
var visitas = 0;
// Iniciando o Socket.IO através do evento Connection.
io.sockets.on('connection', function(socket){
  // Evento message que ocorre quando entra um novo usuário.
  socket.on('message', function(){
    visitas++;
    // Servidor responde apenas para o usuário visitante.
    socket.emit('message', visitas);
    // Servidor responde o mesmo resultado via broadcast.
    socket.broadcast.emit('message', visitas);
  });
  // Evento disconnect, padrão do Socket.io 
  // Trata os dados quando alguém sai da página.
  socket.on('disconnect', function(){
    visitas--;
    // Resposta do servidor via broadcast.
    socket.broadcast.emit('message', visitas);
  });
});

Resumindo, criei um servidor para ler um arquivo index.html em sua rota principal, instanciei e configurei dois eventos do Socket.IO pelo qual utilizei o evento padrão "disconnect" e criei um evento chamado "message", ambos os eventos processam a variável visitas incrementando ou decrementando o seu valor, e após isso, o servidor envia de volta para o cliente através dos métodos emit() que envia apenas para o usuário que conectou e broadcast.emit() que envia as informações para todos os usuários, exceto o usuário que solicitou o processamento.

Agora no lado cliente, apenas adicione o arquivo "/socket.io/socket.io.js" na tag script que automaticamente o módulo Socket.io irá incluí-lo para uso.

<html>
  <head>
    <script src=/socket.io/socket.io.js></script>
    <script>
    // Criando uma conexão Socket.io com servidor.
    var socket = io.connect('http://localhost:8080');
    // Ao conectar com servidor...
    socket.on('connect', function(){
      // Enviando mensagem ao servidor apenas para alertar o servidor.
      socket.send(Ola Servidor);
      // Evento message de resposta do servidor
      // Ao receber uma mensagem do servidor,
      // atualizar a tag de visitas.
      socket.on('message', function(visitas){
        document.getElementById('visitas').innerHTML = visitas;
      });
    });
    </script>
  </head>
  <body>
    <p>Contador de visitas online com Socket.io</p>
    <p>Número de visitas: <span id="visitas">0</span></p>
  </body>
</html>

Esta foi uma simples demonstração do poder oferecido pelo Node.js com Socket.io para implementar funcionalidades em real-time.

Para melhores referências, segue abaixo alguns links importantes:

See you on my next post!