funmachine

Um chat simples com flash e Node.js

2 comentários

Vamos criar um chat simples realtime usando tecnologia flash para o cliente e node.js para o servidor. À uns tempos atrás programar sockets era, muitas vezes, uma dor de cabeça, mas hoje, muito devido à necessidade da web 2.0 de ligar milhares de clientes com o máximo de performance possível, começaram a surgir uma série de framework que permitem programar servidores “nonblocking”, isto é, o servidor não precisa de processo um pedido completo antes de começar a processar o próximo. A ideia deste tutorial foi explorar a framework node.js, com o seu mecanismo assíncrono para processar pedidos.

Começamos por criar um novo ficheiro flash as2.
No primeiro frame insere um componente Texto para visualizar todas as mensagens do chat, um input de texto para enviar escrever uma mensagem e um componente Botão para submeter as mensagens. Nomeia-os da seguinte maneira:

  • Componente Texto: outputText
  • Input de texto: inputText
  • Componente Botão: sendBt

    interface chat flash

De seguida vamos escrever algum código actionscript no frame 1, este vai permitir a conexão a um servidor via socket para enviar e receber mensagens.

Começamos criar um objecto XmlSocket:

mySocket = new XMLSocket();

A seguir programamos uma função que é invocada quando um evento de conexão com a socket for disparado:

mySocket.onConnect = function(success)  {
	 if(success){
		   outputText.htmlText += "<strong>Server connection established!</strong>";
	 }else{
		   outputText.htmlText += "<strong>Server connection failed!</strong>";
	}
 };

E a função quando a conexão é terminada:

mySocket.onClose = function() {
	outputText.htmlText += "<strong>Server connection lost</strong>";
};

De seguida a função quando o cliente receber dados do servidor (as mensagens do chat):

XMLSocket.prototype.onData = function(msg) {
	outputText.htmlText += msg;
};

Agora podemos finalmente conectar o cliente flash a um servidor chat:

mySocket.connect("127.0.0.1", 8124);

Uma pequena nota, regra geral, os portos menores que 1024 são reservados a serviços mais importantes e típicos, por exemplo SMTP,HTTP, daí ser boa prática conectar com portos maiores que 1024 nas tuas aplicações. Por fim vamos criar a funcionalidade do botão de submissão das mensagens:

function sendMessage() {
	if (inputText.htmlText != "")
	{
		mySocket.send(inputText.htmlText+"\n");
		inputText.htmlText = "";
	}
}
sendBt.onRelease = function() {
	sendMessage();
};

E terminamos do lado do cliente, fica o código completo:

mySocket = new XMLSocket();
mySocket.onConnect = function(success) {
	if (success) {
		outputText.htmlText += "<b>Server connection established!</b>";
	}
	else {
		outputText.htmlText += "<b>Server connection failed!</b>";
	}
};

mySocket.onClose = function() {
	outputText.htmlText += "<b>Server connection lost</b>";
};

XMLSocket.prototype.onData = function(msg) {
	outputText.htmlText += msg;
};

mySocket.connect("127.0.0.1", 8124);

function sendMessage() {
	if (inputText.htmlText != "")
	{
		mySocket.send(inputText.htmlText+"\n");
		inputText.htmlText = "";
	}
}
sendBt.onRelease = function() {
	sendMessage();
};

Agora vamos programar um servidor sockets, que vai receber conexões do(s) cliente(s) flash que acabamos de implementar e gerir a recepção e envio de mensagem do chat.
Vamos implementar o servidor em Node.js, uma framework javascript que corre no servidor e permitir implementar servidores de forma “nonblocking”. Vê este post se ainda não sabe o que é o node.js.

Com Node.js, programar sockets é mais simples e além disso retiramos grande vantagem da herança “nonblocking” e orientado a eventos do javascript. O código é bastante simples e a documentação suficiente para perceber o que estamos a fazer.
O que fazemos é criar um servidor TCP e aceitar conexões socket no porto 8124. Depois definimos uma série de callbacks que são chamadas quando o cliente se conecta, envia mensagens ou perdemos a ligação com um cliente. Quando o cliente se conecta, guardamos este numa lista, para posteriormente poder gerir os clientes e fazer broadcast das mensagem para todos.

net = require('net');
var clients = [];

// Iniciar o servidor TCP
net.createServer(function (socket) {
  // Identificar o cliente
  socket.name = socket.remoteAddress + ":" + socket.remotePort
  // colocar o cliente na lista de clientes
  clients.push(socket);
  // Anunciar ao cliente que se conectou e difundir aos restante clientes
  socket.write("Bem vindo " + socket.name + "\n");
  broadcast(socket.name + " juntou-se ao chat \n", socket);

  // Trata mensagem que chegam dos clientes
  socket.on('data', function (data) {
    broadcast(socket.name + "> " + data, socket);
  });

  // Remove o cliente da lista quando se desconexa
  socket.on('end', function () {
    clients.splice(clients.indexOf(socket), 1);
    broadcast(socket.name + " saiu do chat.\n");
  });

  // Envia uma mensagem a todos os clientes
  function broadcast(message, sender) {
    clients.forEach(function (client) {
      client.write(message);
    });
  }
}).listen(8124);

Agora temos o necessário para correr o nosso chat! Infelizmente correr socket com o flash implica ter que ultrapassar uma série de restrições 😦 Precisamos modificar os settings do flash para aceitar ligações socket, penso que se deve ao facto de estarmos em ambiente as2.

flash settings

flash settings

Mas ainda não acabamos os stresses com o flash 😦 O Flash, assim que um swf se tenta conectar via socket, faz um pedido por um “policy file”, este define a política de acessos. Não vou divagar muito neste assunto, existem duas formas de servir este ficheiro: via socket e via http. Na verdade, o flash tenta sempre primeiro a via socket, tentando se ligar no porto 843 da máquina onde a conexão socket é definida. Só depois é que tenta outras alternativa. Por isso, por razões de performance é preferível servir desta forma. Além disso este processo é automático, ao contrário da via http, que pode ser mais simples (apenas colocar o policy file xml disponível no vossa servidor), mas implica que o código do swf é que tem que tratar de fazer o pedido.
Para servirem o policy file, sigam este link da adobe, que explica e fornece código (python e perl) sobre como o fazer.

De seguida segue um vídeo que demonstra o exemplo a correr, como não tive tempo descrever o que estou a fazer e não gravei voz, segue um pequeno “script”:

– Executar um serviço para disponibilizar o policy file.
– Executar o servidor chat.
– No browser, chamar dois clientes chat.

E por hoje é tudo 😉 Qualquer dúvida deixem um comentário!

Anúncios

2 thoughts on “Um chat simples com flash e Node.js

  1. Olá,

    Não consegui entender o funcionamento do policy file. Estou usando a versão do Nodejs que roda em windows, mas como funciona esta chamada?

    Obrigado.

  2. Olá Daniel,

    Realmente esqueci-me de colocar no post o link para a explicação da adobe sobre policy files: http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html
    Nesse link encontras o código necessário para servir policy files. Apenas tens que alterar o policy file a servir (xml) para abrir os portos que entenderes e depois é basicamente correr o código fornecido (eu usei a versão python), antes de testares o chat.
    Esta questão dos policy files pode mesmo ser uma dor de cabeça 😦

    Ab

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s