PHP - Long Polling

Long Polling é uma técnica utilizada para se obter dados e informações em "tempo real" sem que haja uma requisição por parte do usuário.

Como isso é possível? 
Existem algumas formas disso ser feito, nesse artigo, abordaremos o Long Polling.

Criaremos nesse artigo um pequeno chat, lembre-se que o intuito do artigo não é ensinar a fazer um chat, e sim, demostrar o funcionamento do Long Polling.

Vamos ao nosso arquivo poll.php, ele será responsável em trazer novas mensagens que foram enviadas pelo chat.

set_time_limit(0);

function poll($cur_line){
 // Lê arquivo
 $data = file_get_contents('chat.txt');
 $lines = explode("\n", $data);
 
 // Verifica se o número de linha é igual a linha atual ou se a linha 0 está vazia
 if(count($lines) == $cur_line || empty($lines[0])){
  // Coloca o script para dormir por 1 segundo
  sleep(1); 
  return poll($cur_line);
 }else{
  $ret = array();
  $ret['lines'] = array();
  // Coloca somente as linhas que não foram lidas no vetor
  for($cur_line;$cur_line < count($lines); $cur_line++){
   $ret['lines'][] = $lines[$cur_line];
  }
  // Adciona a linha atual no vetor
  $ret['cur_line'] = $cur_line;
  // Encoda o vetor em json
  return json_encode($ret);
 }
}
echo poll($_POST['cur_line']);

Entendendo o poll.php

No arquivo poll há uma função que recebe como parâmetro o $cur_line, essa é a linha atual do chat. Cada mensagem estará em uma linha de um arquivo .txt.  
Sem muito segredo, a função poll lê o arquivo chat.txt e verifica se há novas linhas no arquivo, caso negativo, ele coloca o programa para dormir durante 1 segundo, isso é muito importante para amenizar o gargalo de processamento.

Caso haja novas linhas, ele coloca as novas linhas em um vetor que é encodado para json.

Javascript:

var cur_line = 0;
var poll;
function get_messages(){
 poll = $.ajax({
 type: "POST",
 url: "poll.php",
 data: { 'cur_line' : cur_line },
 dataType: "json",
 success: function(json, textStatus, jqXHR) {
  cur_line = json.cur_line;
  
  // Insere linhas na tela 
  for(i=0;i' + json.lines[i] + '');
   $("#chat #chat-content .messages").prepend(line);
  }
  
 },
 complete: function(){ 
  get_messages();
 },
 timeout: 30000
 });
}

A função get_messages envia um post para o arquivo poll.php e imprime em uma lista o resultado(json) retornado e atualiza o número de linhas carregadas, que vem no json retornado.

Eu sempre recomendo que a conexão seja interrompida de tempo em tempo. No meu caso dixei o timeout em 30 segundos. Isso evita que, em caso de erros, o servidor fique com o processo travado.

Quando requisição é completada, eu chamo a função get_messages novamente, fazendo com que sempre haja uma conexão ativa com o servidor.

Com o Long Polling o chat sempre estará trazendo as novas mensagens de forma rápida, sem precisar ficar enviando milhares de requisições para o servidor.

Se quiser o projeto completo, eu subi no github.
Segue o link: https://github.com/carlosmaniero/Php-long-polling
Demonstração: http://www.livrodeoracao.com.br/dev/chat/index.php

2 comentários:

Marvin disse...

poderia fazer um exemplo de um long polling com banco de dados sql?

Lauro Daniel disse...

Muito obrigado amigo, vou estudar seu código para implementar num sistema.