Fala galera! O capítulo de hoje será muito interessante, falarei sobre um assunto que esta muito emergente nos sistemas web, que esta sendo largamente utilizado no Node.js, o assunto é Real-time.
Quando se fala de aplicações real-time, estamos técnicamente falando de conexões bi-direcionais, que na prática, é uma conexão que se mantem aberta (keep-alive) para que os clientes interajam com o servidor em uma única conexão aberta. A grande vantagem disso é de não precisar mais das requisições assíncronas (AJAX) para simular uma “ação quase real-time”, digo quase pois AJAX não é uma conexão bi-direcional e sim apenas uma conexão uni-direcional que se mantém aberta até o término de seu processamento.
Node.js se tornou popular devido a sua facilidade em trabalhar com real-time, simplesmente por que o protocolo WebSockets (Protocolo do HTML5 para conexões bi-direcionais) utiliza-se Javascript também.
O único problema em desenvolver aplicações real-time é que nem todos os browsers suportam o protocolo WebSockets, com isso ainda é inviável desenvolver uma aplicação 100% WebSockets. Diante desse problema surgiu um framework chamado Socket.IO cuja sua idéia resolve esse problema nos browsers antigos, emulando outras técnicas de comunicação real-time de forma totalmente abstrata para o desenvolvedor.
Basicamente ele possui um script no client-side que detecta o browser e a compatibilidade adequada de comunicação.
Ele tenta na seguinte ordem escolher qual técnica de comunicação será viável com o browser:
- 1 – WebSocket
- 2 – Adobe® Flash® Socket
- 3 – AJAX long polling
- 4 – AJAX multipart streaming
- 5 – Forever Iframe
- 6 – JSONP Polling
Com isso se o navegador for o mais recente Firefox ou Chrome e no server-side estiver habilitado o WebSockets, a comunicação será feita através desse protocolo. Porém se o usuário estiver no IE 6 sem o adobe flash player instalado, o nível de comunicação cai para Ajax long polling ou até JSONP polling, vai depender da decisão que é automática do Socket.IO client-side. Na maioria dos casos atuais, a conexão será através do Adobe Flash Player ou AJAX Long polling.
O legal de tudo isso é que programar com Socket.IO é muito simples e toda decisão complexa é abstraída para o programador.
Abaixo, vejam uma versão simplificada de um chat real-time:
Para executar esse código, execute primeiro o comando:
npm install express socket.io
Arquivo: server.js
// É necessário instanciar os módulos abaixo nessa ordem!
var app = require('express')()
, server = require('http').createServer(app)
, io = require('socket.io').listen(server);
server.listen(3000, function(){
console.log("Chat real-time...");
});
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
// Eventos do Socket.IO
io.sockets.on('connection', function (socket) {
socket.on('toServer', function (data) {
var msg = "<b>"+data.nome+":</b> "+data.msg+"<br>";
socket.emit('toClient', msg);
socket.broadcast.emit('toClient', msg);
});
});
Arquivo: index.html
<html>
<head>
<title>Chat Real-time</title>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('toClient', function (msg) {
document.getElementById('historico').innerHTML += msg;
});
var enviar = function(){
var nome = document.getElementById('nome').value;
var msg = document.getElementById('mensagem').value;
socket.emit('toServer', {nome: nome, msg: msg});
};
</script>
</head>
<body>
<h1>Chat Real-time</h1>
<label> Nome:
<input type="text" id="nome" size="3">
</label>
<label> Mensagem:
<input type="text" id="mensagem" size="10">
</label>
<button id="enviar" onclick="enviar();">Enviar</button>
<hr>
<div id="historico"></div>
</body>
</html>
Acabamos de criar uma versão simples de um chat em real-time!
No arquivo server.js somos obrigados a instanciar os módulos express, http e socket.io naquela ordem, pois é um motivo específico do próprio Socket.IO em que ele precisa escutar todas as ações do módulo http primeiro.
Lembrando que estamos usando as últimas versões de todos esses módulos: Express 3 e Socket.IO 0.9.x.
A boa prática é seguir exatamente a ordem apresentada neste exemplo anterior, que seria instanciar os módulos já deixando o express e socket.io executando seus métodos de listen(), depois criamos as rotas do express e por último os eventos real-time do socket.io.
Os eventos do Socket.IO, por padrão no server-side são:
- io.sockets.on(‘connection’, function(socket){}) - Ocorre quando o servidor recebe uma nova conexão de cliente
- socket.on(‘message’, function(mensagem, callback){}) - Ocorre quando um cliente usa a função send();, o callback desse evento serve para automaticamente responder o cliente no final da execução deste evento.
- socket.on(‘qualquer-nome-de-evento’, function(data)) - Eventos customizados pelo desenvolvedor, qualquer nome pode ser apelidado aqui e o seu comportamento é de apenas receber através do data dados enviados pelo cliente. No nosso exemplo prático, criamos o evento toServer.
- socket.on(‘disconnect’) - Ocorre quando um cliente sai da área conectada ou emite o evento disconnect para o servidor.
Quando queremos enviar uma mensagem para o cliente, temos duas funções:
- socket.emit(‘evento’, variaveis): Envia uma mensagem para o cliente que se comunicou com o servidor.
- socket.broadcast.emit(‘evento’, variaveis): Envia uma mensagem para todos os clientes conectados ao servidor, exceto o cliente que se comunicou com o servidor, ou seja, se numa sala de chat temos 4 clientes e o cliente X emitiu uma mensagem ao servidor, os outros 3 clientes receberão o retorno de uma mensagem menos o cliente X.
No lado cliente, temos alguns pontos a serem explicados!
Adicionamos a tag: <script src="/socket.io/socket.io.js"></script> que é automaticamente incluída pelo Socket.IO, não se preocupe em baixar e incluir esse arquivo js na sua pasta de arquivos estáticos.
Outro detalhe é que para o envio de mensagens temos apenas a função: socket.emit()
E no client-side trabalhamos com novos eventos:
- socket.on(‘connect’, function () {}) – Ocorre quando o cliente se conecta ao servidor.
- socket.on(‘connecting’, function () {}) – Ocorre quando o cliente esta se conectando ao servidor.
- socket.on(‘disconnect’, function () {}) – Ocorre quando o cliente deseja se desconectar do servidor.
- socket.on(‘connect_failed’, function () {}) – Ocorre quando o cliente não conseguiu se conectar no servidor.
- socket.on(‘error’, function () {}) – Ocorre quando o cliente já se conectou, porém ocorreu um erro grave no servidor durante as trocas de mensagens.
- socket.on(‘message’, function (message, callback) {}) – Ocorre quando o cliente envia uma mensagem de resposta rápida ao servidor, cuja resposta acontece através da função de callback.
- socket.on(‘qualquer-nome-de-evento’, function (data) {}) – Evento customizado pelo desenvolvedor. No nosso exemplo criamos o evento toClient.
- socket.on(‘reconnect_failed’, function () {}) – Ocorre quando o cliente não consegue se reconectar ao servidor.
- socket.on(‘reconnect’, function () {}) – Ocorre quando o cliente se reconecta ao servidor.
- socket.on(‘reconnecting’, function () {}) – Ocorre quando o cliente esta se reconectando ao servidor.
Bom galera, esse foi mais um capítulo do mini-curso!
Para melhores referências, segue abaixo os links utilizados:
Até a próxima! E Feliz 2013 a todos!


valeu o post vou ler todo o blog agora
Parabéns pelo Post! Adorei, muito explicativo.
A comunidade brasileira agradece.
Muito obrigado Rafael, fico feliz em saber que gostou do post.
Por favor, ajude-me a divulgar pelas as comunidades brasileiras de Node.js
Obrigado!
Post bacana. Esclareceu de forma prática
Boa. Abraço.