Server Push: Long Polling usando PHP

Server Push: Long Polling usando PHP

Há situações em que precisamos obter uma resposta de um servidor a cada X intervalo de tempo. Alguns programadores criam rotinas que ficam perguntando para o servidor toda hora. O problema dessa abordagem é que ela sobrecarrega o servidor com muitas requisições, aumentando tráfego de rede e podendo até derrubar o servidor.

A técnica do Server Push consiste em manter uma conexão aberta entre cliente e servidor. Quando houver conteúdo para o servidor enviar ao cliente, ele o envia. Assim, o cliente não precisa ficar “perguntando” para o servidor se ele tem novo conteúdo.

Para que já programou usando sockets TCP/IP, por exemplo, parece bem simples. O problema de fazer isso via HTTP é que este protocolo não permite conexões persistentes, ou seja, o servidor recebe uma requisição, responde-a e fecha a conexão. Para contornar isso, usaremos o que é chamado de Long Polling, descrito com mais detalhes no link abaixo:

http://en.wikipedia.org/wiki/Push_technology#Long_polling

Em suma, a técnica consiste no seguinte: o cliente faz uma requisição ao servidor. Se o servidor tiver conteúdo para mandar, manda-o e fecha a conexão. Caso ele não tenha nada para enviar, aguarda mais um tempo e verifica de novo. Ou seja, o servidor fica em loop infinito, enquanto não tiver dados para enviar. O cliente, ao receber a informação, processa-a e reabre a conexão com o servidor.

Vamos a um exemplo de implementação.

Servidor (server.php):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
// arquivo cujo conteúdo será enviado ao cliente
$dataFileName = 'data.txt'; 
 
while ( true )
{
    $requestedTimestamp = isset( $_GET['timestamp'] ) ? (int)$_GET['timestamp'] : null;      
 
    // o PHP faz cache de operações "stat" do filesystem. Por isso, devemos limpar esse cache   
    clearstatcache();  
 
    $modifiedAt = filemtime( $dataFileName );       
 
    if ( $requestedTimestamp == null || $modifiedAt > $requestedTimestamp )
    {
        $data = file_get_contents( $dataFileName );
 
        $arrData = array(
            'content' => $data,
            'timestamp' => $modifiedAt
        );
 
        $json = json_encode( $arrData );
 
        echo $json;
 
        break;
    }
    else
    {
        sleep( 2 );
        continue;
    }
}

Cliente (client.js):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getContent( timestamp )
{
    var queryString = { 'timestamp' : timestamp };
 
    $.get ( 'server.php' , queryString , function ( data )
    {
        var obj = jQuery.parseJSON( data );
        $( '#response' ).html( obj.content );
 
        // reconecta ao receber uma resposta do servidor
        getContent( obj.timestamp );
    });
}
 
$( document ).ready ( function ()
{
    getContent();
});

index.php

1
2
<script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
<script src="client.js" type="text/javascript"></script>

Conteúdo

Crie um arquivo data.txt e modifique o conteúdo dele enquanto está com o cliente aberto (lembre-se de salvar o conteúdo do data.txt a cada modificação). A cada modificação, o novo conteúdo é exibido no cliente.

É importante notar que esse é um exemplo bem cru. É necessário implementar um timeout no servidor. Veja que, se o cliente desconectar antes de o servidor enviar uma resposta, este ficará com um processo em loop infinito, podendo se estender indefinidamente, caso nunca mais haja conteúdo a ser enviado como resposta para aquela requisição.

O código completo está no meu GitHub, neste link:
https://github.com/beraldo/Server-Push

De brinde, nesse link também há um cliente feito para iOS, que fiz para testes e resolvi colocar junto no repositório. :)

Exemplo Usando Banco de Dados

Muitos me perguntam como usar Long Polling com banco de dados em vez de fazer com arquivo de texto. Por isso vou incluir um exemplo usando um simples banco de dados, em SQLite. Vou usar a classe PDO para comunicação com o banco. Assim o exemplo é adaptável a qualquer outro SGBD. Caso não saiba como trabalhar com PDO, recomendo ler este post.

Primeiramente, vou criar um banco de dados SQLite, com o nome de comments.db, onde criarei uma tabela que armazenará comentários. A tabela possui os campos id, author, comment e timestamp. É por este último campo que faremos a busca, filtrando por timestamps superiores ao passado por parâmetro para o script. Usarei este comando para criar a base de dados:

$ sqlite3 comments.db "CREATE TABLE comments(id INTEGER PRIMARY KEY, author VARCHAR, comment TEXT, timestamp INTEGER);"

Tendo o banco criado, podemos alterar o arquivo server.php, para utilizá-lo em vez de ler o arquivo data.txt. O script ficará assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$dbFile = 'comments.db';
 
$PDO = new PDO( "sqlite:" . $dbFile );
 
$requestedTimestamp = isset ( $_GET [ 'timestamp' ] ) ? (int)$_GET [ 'timestamp' ] : time();
 
while ( true )
{
    $stmt = $PDO->prepare( "SELECT author, comment, timestamp FROM comments WHERE timestamp > :requestedTimestamp" );
    $stmt->bindParam( ':requestedTimestamp', $requestedTimestamp );
    $stmt->execute();
    $rows = $stmt->fetchAll( PDO::FETCH_ASSOC );
 
    if ( count( $rows ) > 0 )
    {
        $json = json_encode( $rows );
        echo $json;
        break;
    }
    else
    {
        sleep( 2 );
        continue;
    }
}

NOTA: para usar MysQL em vez do SQLite, basta trocar estas duas linhas:

$dbFile = 'comments.db';
$PDO = new PDO( "sqlite:" . $dbFile );

Por esta:

$PDO = new PDO( 'mysql:host=servidor_mysql;dbname=nome_do_banco', 'usuario', 'senha' );

Para mais detalhes sobre como usar PDO com MySQL, veja este post.

Vamos precisar mudar um pouco nosso cliente Javascript, deixando desta forma:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getContent( timestamp )
{
    var queryString = { 'timestamp' : timestamp };
    $.get ( 'server.php' , queryString , function ( data )
    {
        var obj = jQuery.parseJSON( data );
 
        for (var k in obj)
        {
            var comment = "<p>" + obj[k].comment + "</p>";
            var timestamp = obj[k].timestamp;
            $( '#response' ).append( comment );
        }
 
        // reconecta ao receber uma resposta do servidor
        getContent( timestamp );
    });
}
 
$( document ).ready( function ()
{
    getContent();
});

Enquanto o script server.php estiver em execução, você deve fazer um INSERT na tabela comments, inserindo um registro com o timestamp superior ao atual. Por exemplo:

INSERT INTO comments(author, comment, TIMESTAMP) VALUES('Beraldo', 'Oi, sou um comentário', 1421002330);

ATENÇÃO: Lembre-se de alterar o timestamp do INSERT acima para um que seja superior ao timestamp atual.

Pronto. Agora você tem um exemplo de Long Polling usando banco de dados. :)

 

Aprenda Ainda Mais

15 Dicas, Boas Práticas e Fundamentos do PHP

Conheça Dicas FUNDAMENTAIS para programar em PHP de forma Profissional

Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!

Baixe gratuitamente este guia com 15 Dicas de PHP

The following two tabs change content below.
Graduado em Ciência da Computação, pela Universidade Federal do Paraná (UFPR), é desenvolvedor de software desde 2008, com foco em Desenvolvimento Web com PHP.
  • Sensacional este artigo .. até agora o mais explicativo que encontrei ! Obrigado por compartilhar seu conhecimento conosco!

  • Elvis

    Concordo totalmente com o comentário do Juliano. O artigo mais explicativo que vi até agora.
    Só gostaria de perguntar ao autor onde devo colocar exatamente o timeout. obrigado e parabens.

    • Obrigado! É bom saber que o post está sendo útil :)

      O timeout você coloca no servidor (PHP). Caso não haja requisição, dá um break no loop.

  • daniel

    beraldo, p mim nao funcionou
    copiei e colei o codigo e nao rolou

  • Kaká

    Muito simples e eficiente. É bom adicionar set_time_limit(0) para evitar que o script seja terminado caso exceda max_execution_time. Obrigado.

  • Anderson

    Bom dia…
    Gostaria de saber se usando a ideia acima, consigo ter um bom desempenho em um sistema que fica on line mais de 30 pessoas ao mesmo tempo.
    Pretendo adicionar leitura no BD e algumas coisas a mais no script, porem tenho receio de que lá na frente fique limitado ao servidor.
    Obrigado e muito bom o script.

    • Olá.
      Para quantidades baixas de usuário, não haveria problema. O uso do sleep com parâmetro maior pode reduzir o consumo de CPU quando houver muitos usuários. Você pode acompanhar o uso da CPU durante os acessos. Caso ele fique muito alto, experimente passar parâmetreos maiores para o sleep

  • Lucas santos

    Olá muito bom mas como eu faço para usar o meu código ai já tentei de vários jeitos e nada funcionou :(

    Autor:

    Criado em:

     

  • Lucas santos

    include “conexao.php”;
    $sql = mysql_query (“SELECT * FROM noticias LIMIT 3”);
    while ($exibe = mysql_fetch_assoc($sql)){

    • O include você deixa no topo do arquivo. A consulta deve ir dentro do while, onde, no exemplo, é feita a verificação do arquivo

      • Lucas santos

        Muito bom ajudou muito!

  • Josimara

    Olá eu estou usando $dataFileName = ‘data.php’; o arquivo data.php contem uma consulta no banco de dados mas quando eu entro no index.php só aparece o html do arquivo data.php e o php não, como eu posso revolver isso obrigado, tem um monte de gente usando esse seu código essa mesma duvida.

    • Olá. Qua. é o conteúdo exato do arquivo? Se for um script PHP, um fread() vai trazer inclusive as tags do PHP e tudo será interpretado como HTML. Tente usar eval()

  • Renato

    Parabéns pelo tutorial, Beraldo. Seria possível fazer um exemplo (aqui mesmo nos comentários) usando mySQL ao invés de extrair os dados pelo arquivo.txt?

    Abraço!

  • Daniel Rovay

    Boa noite,

    desculpa esta escrevendo mas estou com uma duvida, na vdd a mesma duvida da Josimara, sera que alguem ja conseguiu resolver esse problema ??

    Obrigado.

  • Marcello Leibovich

    Estou tentando usar seu código com uma consulta em um banco MYSQL ao invés de um arquivo TXT. Mas não obtive sucesso. Ví que outras pessoas tem a mesma dificuldade. Poderia fazer um tutorial mostrando o long polling com MYSQL ?

  • Muito bom, introduzir no codeigniter vai ficar top..

  • David Damasceno

    Gostaria de saber como ficará o código Javascript, se você usou Post ou ajax mesmo?

    • Olá, David

      Nesse exemplo eu fiz uma requisição GET por ajax, usando o jQuery. Você pode usar POST, se preferir

  • AD

    Beraldo, belo tutorial. Muito simples e muitíssimo explicativo.
    Consegui fazer tudo com o arquivo txt porém, ao realizar via web com o banco de dados, a página não atualiza.
    Ela não recebe os dados.
    Estou desenvolvendo em localhost, testei no meu server mas tbm não foi.
    Pode me ajudar?

  • Felipe Nogueira Bezerra

    Sou estudante e adoraria de ter um arquivo exemplo para melhor estudar. Ficar muito agradecido se pudesse me fornecer um arquivo com conteúdo completo ou uma base qualquer. E meus colegas de classe iriam agradecer também.

    • Olá

      Os códigos estão no Github, neste link https://github.com/beraldo/Server-Push

      • Felipe Nogueira Bezerra

        E o código usando Banco de dados não deu certo, e não está no Github.

        • O trecho usando banco de dados não está no Github mesmo. Adicionei recentemente, pois muitos estavam com dificuldades de implementar essa lógica usando BD.

          Usei PDO, por ser genérico, mas pode usar MySQLi, por exemplo. Porém recomendo PDO.

  • Lucas

    Beraldo, parabéns!!! ótimo post!!

    Não estava conseguindo pois estava errando na página client, mas olhando o exemplo no github matei!!!

    Por ser algo que muitos ainda desconhecem, ou estão iniciando (inclusive eu), você poderia escrever um novo post, com técnicas melhoradas, incluindo que o sleep que citou!

    Abs

  • Ótimo!

  • Samuelson

    O meu ficou sobrecarregado.

  • Rafael

    Depois de um tempinho sem alterar o arquivo txt, ele da erro.

    server.php?timestamp=1442878082 500 (Internal Server Error)

    • Olá, Rafael

      O erro 500 é um erro genérico. Há várias causas. Você precisa olhar os logs do servidor web para ver a mensagem de erro detalhada.

  • Gabriel Gomes

    O exemplo com banco de dados nao esta funcionando aqui,nenhuma mensagem aparece

    • Olá, Gabriel.

      Habilite todas as exibições de erro e também faça debug da query. Mostro como fazer isso neste tópico: http://forum.imasters.com.br/topic/542539-atencao-orientacoes-e-regras-do-forum-de-php/

      • Gabriel Gomes

        Então roberto eu ainda não consegui mostrar o resultado do mysql na index.php , porem o resultado aparece na server.php “[{“author”:”gabriel”,”comment”:”testetestetesteteste”,”timestamp”:”1446935295″}]”,
        mas nao consigo passar ele para a index.php, outra coisa que eu observei depois que eu consegui inserir os dados do bd na server.php a pagina index.php fica fazendo requisições infinitas do server.php …… tem algum jeito de eu passar as informações do server.php para a index e a mesma nao ficar fazendo milhares de requisições ? sera que o problema pode constar no while(true) que esta na (server.php) ou no client.js ?

        • Aparentemente seu problema está todo no Javascript. Se o server.php exibe o retorno, até aí está OK. Agora falta puxar esses dados no JS.
          E se está havendo infinitas requisições, é no JS também. O loop dentro do PHP não gera requisição a mais, ele apenas mantém aberta a requisição corrente

          • Gabriel Gomes

            Roberto estou com problema no js mesmo mas nao encontro o erro , poderia me ajudar ?

            ***************index.php********************

            Conteúdo

            ***************server.php********************

            prepare( “SELECT author, comment, timestamp FROM comments WHERE timestamp bindParam( ‘:requestedTimestamp’, $requestedTimestamp );
            $stmt->execute();

            $rows = $stmt->fetchAll( PDO::FETCH_ASSOC );

            if ( count( $rows ) > 0 )
            {

            $json = json_encode( $rows );

            echo $json;
            break;
            }
            else
            {
            sleep( 2 );
            continue;
            }
            }
            ?>

            ***************client.js********************
            function getContent( timestamp )
            {
            var queryString = { ‘timestamp’ : timestamp };

            $.get ( ‘server.php’ , queryString , function ( data )
            {
            var obj = jQuery.parseJSON( data );
            $( ‘#response’ ).html( obj.content );

            // reconecta ao receber uma resposta do servidor
            getContent( obj.timestamp );
            });
            }

            $( document ).ready ( function ()
            {
            getContent();
            });

            ***************************************************************

            *O js nao me retorna nada para a div “response” da index

            *estou listando todos os dados anteriores ao timestamp atual :

            $stmt = $PDO->prepare( “SELECT author, comment, timestamp FROM comments WHERE timestamp <= :requestedTimestamp" );

            • Gabriel Gomes

              mandei a server.php errada acima ……. segue a correta

              prepare( “SELECT author, comment, timestamp FROM comments WHERE timestamp bindParam( ‘:requestedTimestamp’, $requestedTimestamp );
              $stmt->execute();

              $rows = $stmt->fetchAll( PDO::FETCH_ASSOC );

              if ( count( $rows ) > 0 )
              {

              $json = json_encode( $rows );

              echo $json;
              break;
              }
              else
              {
              sleep( 2 );
              continue;
              }
              }
              ?>

            • Gabriel Gomes

              o comentário acima escondeu essas linhas do server.php

              $PDO = new PDO( ‘mysql:host=localhost;dbname=nome_do_banco’, ‘root’, ” );

              while ( true )

              {

              $requestedTimestamp = isset ( $_GET [ ‘timestamp’ ] ) ? (int)$_GET [ ‘timestamp’ ] : time();

              $stmt = $PDO->

              • Seu código tem um erro na condição do WHERE, que busca dados anteriores ao timestamp.
                Mas o meu exemplo também tinha alguns erros. Acabei de corrigir. Copie a nova versão que acabei de colocar aqui no post e teste de novo

                • Gabriel Gomes

                  Agora eu consegui !

                  para mostrar os resultados anteriores,implementei para que o timestamp no banco de dados tenha valores negativos a cada insert (-1,-2,-3-4….etc) e essa linha $stmt = $PDO->prepare( “SELECT author, comment, timestamp FROM comments WHERE timestamp <= :requestedTimestamp" ); deixei para ver numeros menores ou iguais

                  Roberto Obrigado pela atenção

                  • Gabriel Gomes

                    roberto ok mas é certo a pagina cair depois de algumas horas ?? pq o request fica la aberto durante horas ,, e se eu fazer que esse request fique fechando a cada x segundos sobrecarrega meu servidor tbm, oque fazer ?

                    • Eu recomendo criar um timeout no servidor. Depois de X tempo sem resposta, dá um break para encerrar o script. O tempo X vai variar conforme sua apoicação

                    • Welisvelton Cabral

                      Um timeout seria utilizando por exemplo a set_time_limit() ?

                    • Um timeout é uma forma de encerrar a rotina caso ela não tenha resposta após X tempo.
                      Você salva o horário do início do script e, dentro do loop, verifica a hora corrente. Se for maior que 5 minutos em relação à hora inicial, quer dizer que o script está rodando a 10 minutos sem gerar resposta ao cliente. Caso isso aconteça, encerre o loop e o script

                    • Welisvelton Cabral

                      Perdoe-me, mas poderia mostrar como fazer isso? Estou meio perdido

                    • A ideia é a mesma da apresentada neste tópico, na função perform_task():
                      https://stackoverflow.com/a/10587359/1233120

  • Hackaid Tecnologia

    Roberto, adorei o exemplo. Estou fazendo um teste. Gostaria de usar em uma apresentação de Hangout. Tipo vamos apresentar em evento na internet e gostaríamos de no final mostrar o botão ou campo para deixar mensagem. Estava pensando em usar esse exemplo. Meu medo é por exemplo, após uma duas horas, e eu realizar a modificação ele ainda irá transmitir essa mudança e mostrar o conteúdo? Mesmo com várias pessoas conectadas ao embed do Hangout? Muito obrigado! Estava procurando por isso faz tempo.

    • Olá. Não entendi sua dúvida. Após duas horas, que modificação você pretende fazer?

      • Hackaid Tecnologia

        Roberto,

        Apenas alterar o arquivo data.txt ou fazer uma alteração no bd. A dúvida mesmo é se essa conexão com o servidor continua por um longo período. Por exemplo no caso de uma palestra ao vivo. O visitante vai estar na página vendo o embed do Hangou por uma ou duas horas. Aí ao final faria uma alteração para ele ter acesso ao link ou botão. Ele receberá essa alteração?

        • O loop roda por tempo indeterminado. Até por isso eu sugiro implementar um timeout, conforme o tipo da aplicação. Mas se não houver esse timeout, o loop ficará sempre sendo executado, até que a modificação seja feita

  • Francisco couto

    OLÁ!! pelo que entendi quando ele recebe uma “alteração” ele para “brak” o while e como fazer ele funcionar como um push?

  • Francisco couto

    desculpe se estou sendo estupido nas perguntas mas tenho a seguinte duvida, esse script sobrecarrega o servidor em caso de várias pessoas conectadas ao mesmo tempo?
    se o usuário fechar o browser o script é encerrado no servidor?

    • Olá
      Essa técnica só vai sobrecarregar muito o servidor se o loop não tiver uma espera grande (função sleep). No exemplo, uso sleep(2), aguardando dois segundos antes de iniciar o loop de novo. Retire o sleep e acompanhe os níveis da CPU. Verá que haverá bastante sobrecarga.
      Porém usar WebSockets é ainda melhor. Server Push é útil quando não é possível abrir um socket no servidor.
      E o script não encerra ao fechar o navegador. Por isso sugeri implementar um timeout para encerrar o script após X minutos sem resposta

      • Francisco couto

        Entendi, fiz os testes aqui e deu certo!! Muitíssimo obrigado, com relação ao WebSockets, é possivel implementar no php.? Ps. Ainda nao li sobreisso, vou começar agora msmo… Fiz um chat interno onde eu trabalho só q utilizei setInterval() do javascript q busca via ajax a cada 2 segundos, só q quando todos estão conectados ao mesmo tempo o Apache cai e volta e o log ficando gigante. Obrigado…

        • Esse é o grande problema de fazer requisições a cada X segundos. Com muitos usuários, isso se torna praticamente um ataque DDoS. Por isso a técnica de Server Push é melhor.
          Sobre WebSockets não posso falar muito, pois usei pouco. O que vi até hoje é principalmente em Node.js, mas creio que também haja soluções em PHP. Isso para o servidor. O cliente é sempre JS, assim como é no Server Push também

          • Francisco couto

            show de bola, testei aqui e tudo ok, agora vou ver como verificar se o usuário está logado pois se colocar um timeout muito curto vai dar na mesma de setInterval pois a cada timeout que o php fizer se o usuário ainda estiver com a tela aberta vai fazer outra requisição ao php, se conseguir verificar se não está logado posso parar o loop.

            • Acho que você não entendeu a ideia do timeout. Não tem nada a ver com setTimeout do Javascript.
              Ele é um “contador” no próprio PHP. Por exemplo, pegue a hora inicial do script e compare com a atual. Se for maior que 30 minutos, por exemplo, encerre o loop e retorne um JSON dizendo que não houve resultados. Se o usuário já tiver fechado o navegador, o script para e pronto; se o navegador ainda estiver aberto, o JS recebe a resposta e abre uma nova requisição.

              • Francisco couto

                Entendi sim, o q eu quiz dizer é q para um chat q mostra quem está online em tepo real não daria certo pois nesse caso o servidor q envia para o cliente, sendo assim, neste método nao tem como o cliente informar q está online pois teria q enviar em tempo real q está com o navegador aberto, pra isso teria q colocar em vez de 30 min, 1 seg e isso voltaria na questão em q varias pessoas conectadas ao mesmo tempo valeria quase q um ataque DDOS, o meu objetivo é manter uma conexão doreta entre o servidor e o cliente e estou vendo q só como vc citou anteriomente sobre o WebSockets

                • Francisco couto

                  Quer q eu poste a minha idéia? Queria muito q isso funcionasse com php e javascript puro pois são as linguagens q eu tenho um certo “DOMÍNIO” por assim dizer.

  • Francisco couto

    uma maneira de verificar seria utilizando session só que a pagina fica carregando não vai quando coloco session_start, enquanto o loop não parar nenhuma outra página carrega. Acho que o jeito será estudar o WebSockets ou similares, que pena!!

  • Raoni

    Muito interessante o conceito, mas hoje o loop while vai trancar o servidor, não deixando fazer mais nada enquanto o loop não for encerrado.

  • Thiago Dias

    Aqui não funcionou, só não atualizei o timestamp da tabela, pois não entendi essa parte direito, o arquivo server.php fica carregando por um tempo e depois me retorna: ”
    Fatal error: Maximum execution time of 30 seconds exceeded” , isso não funciona pelo fato de não ter atualizado o timestamp para o atual?

    • Esse erro é devido ao limite de execução do PHP. Para remover esse limite, coloque esta linha no topo do script:

      set_time_limit(0);

      • Thiago Dias

        Ainda assim não funcionou, Tenho que ficar mudando o timestamp no banco de dados de forma manual?

        • Thiago Dias

          Ele fica carregando “para sempre”, você todo código pronto com a estrutura SQL?

          • A ideia é exatamente essa. O script fica carregando até que um registro com timestamp maior que o passado por parâmetro seja identificado (o que caracteriza um registro novo). Então você deve inserir um novo registro ou atualizar um timestamp no banco

      • Thiago Dias

        Tentei fazer do 0, agora obtive uma resposta diferente, o script é chamado e exibido na index, só que fica fazendo infinitas chamadas ao “server.php”, o que pode ser isso?

  • LUIZ A. G.

    Funcionou que é uma beleza, e Para mostrar o total. como faço.

  • LUIZ A. G.

    opa, tirou o meu site do ar, por causa do loop. já abandonei….

    • Depende do intervalo entre cada iteração. Se for muito pequeno, vai sobrecarregar, mesmo. Outro ponto importante é o timeout para encerrar o script caso não haja resposta em X segundos, por exemplo

      • LUIZ A. G.

        Teria outra forma de obter esses dados sem forçar o servidor.