É mais simples do que eu pensava inicialmente. Basicamente, você tem uma página que não faz nada, até que os dados que você deseja enviar estejam disponíveis (por exemplo, uma nova mensagem chega).
Aqui está um exemplo realmente básico, que envia uma sequência simples após 2-10 segundos. 1 em 3 chances de retornar um erro 404 (para mostrar o tratamento de erros no próximo exemplo de Javascript)
msgsrv.php
<?php
if(rand(1,3) == 1){
/* Fake an error */
header("HTTP/1.0 404 Not Found");
die();
}
/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>
Nota: Em um site real, a execução em um servidor Web comum como o Apache rapidamente amarra todos os "threads de trabalho" e deixa-o incapaz de responder a outras solicitações. Existem maneiras de contornar isso, mas é recomendável escrever um "servidor de pesquisa longa" em algo como o twisted do Python , que não depende de um thread por solicitação. O cometD é popular (disponível em vários idiomas), e o Tornado é uma nova estrutura criada especificamente para essas tarefas (foi criada para o longo código de pesquisa do FriendFeed) ... mas como um exemplo simples, o Apache é mais do que adequado ! Esse script pode ser facilmente escrito em qualquer idioma (eu escolhi o Apache / PHP, pois eles são muito comuns, e eu os estava executando localmente)
Em Javascript, você solicita o arquivo acima ( msg_srv.php
) e aguarda uma resposta. Quando você obtém um, você age com base nos dados. Então você solicita o arquivo e espera novamente, age com base nos dados (e repita)
A seguir, é apresentado um exemplo dessa página. Quando a página é carregada, ela envia a solicitação inicial para o msgsrv.php
arquivo. Se for bem-sucedida, anexamos a mensagem à #messages
div e, após 1 segundo, chamamos a função waitForMsg novamente, o que desencadeia a espera.
O segundo setTimeout()
é um limitador de taxa realmente básico, funciona bem sem isso, mas se msgsrv.php
sempre retorna instantaneamente (com um erro de sintaxe, por exemplo) - você inunda o navegador e pode congelar rapidamente. É melhor verificar se o arquivo contém uma resposta JSON válida e / ou manter um total em execução de solicitações por minuto / segundo e fazer uma pausa apropriada.
Se a página cometer erros, ele anexa o erro à #messages
div, aguarda 15 segundos e tenta novamente (idêntico ao modo como esperamos 1 segundo após cada mensagem)
O bom dessa abordagem é que ela é muito resistente. Se a conexão com a Internet dos clientes morrer, o tempo limite será excedido e, em seguida, tente se reconectar - isso é inerente ao tempo em que a pesquisa funciona, sem a necessidade de tratamento de erros complicado.
De qualquer forma, o long_poller.htm
código, usando a estrutura jQuery:
<html>
<head>
<title>BargePoller</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
body{ background:#000;color:#fff;font-size:.9em; }
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.old{ background-color:#246499;}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
</style>
<script type="text/javascript" charset="utf-8">
function addmsg(type, msg){
/* Simple helper to add a div.
type is the name of a CSS class (old/new/error).
msg is the contents of the div */
$("#messages").append(
"<div class='msg "+ type +"'>"+ msg +"</div>"
);
}
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "msgsrv.php",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
success: function(data){ /* called when request to barge.php completes */
addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
waitForMsg, /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
addmsg("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg, /* Try again after.. */
15000); /* milliseconds (15seconds) */
}
});
};
$(document).ready(function(){
waitForMsg(); /* Start the inital request */
});
</script>
</head>
<body>
<div id="messages">
<div class="msg old">
BargePoll message requester!
</div>
</div>
</body>
</html>
sleep(rand(2,10));
? para não fazer nada, faça uma pesquisa no banco de dados a cada 100 milissegundos? quando ele decide morrer?Eu tenho um exemplo muito simples de bate-papo como parte do slosh .
Editar : (já que todos estão colando seu código aqui)
Este é o bate-papo multiusuário completo baseado em JSON, usando pesquisas longas e slosh . Esta é uma demonstração de como fazer as chamadas; portanto, ignore os problemas do XSS. Ninguém deve implantar isso sem sanitá-lo primeiro.
Observe que o cliente sempre tem uma conexão com o servidor e, assim que alguém envia uma mensagem, todos devem vê-la aproximadamente instantaneamente.
fonte
getNewComments
callback lá, por isso só dispara no final de cada solicitação ajax interminavelmenteO Tornado foi projetado para pesquisas longas e inclui um aplicativo de bate-papo muito mínimo (algumas centenas de linhas de Python) em / examples / chatdemo , incluindo código do servidor e código do cliente JS. Funciona assim:
Os clientes usam o JS para solicitar atualizações, pois (número da última mensagem), o servidor URLHandler as recebe e adiciona um retorno de chamada para responder ao cliente em uma fila.
Quando o servidor recebe uma nova mensagem, o evento onmessage é acionado, percorre os retornos de chamada e envia as mensagens.
O JS do lado do cliente recebe a mensagem, a adiciona à página e solicita atualizações desde esse novo ID de mensagem.
fonte
Eu acho que o cliente parece uma solicitação AJAX assíncrona normal, mas você espera que demore "muito tempo" para voltar.
O servidor fica assim.
Portanto, a solicitação AJAX vai para o servidor, provavelmente incluindo um carimbo de data e hora de quando foi a última atualização, para que você
hasNewData()
saiba quais dados você já obteve. O servidor fica parado em loop até que novos dados estejam disponíveis. O tempo todo, sua solicitação AJAX ainda está conectada, apenas aguardando por dados. Por fim, quando novos dados estão disponíveis, o servidor os envia à sua solicitação AJAX e fecha a conexão.fonte
Aqui estão algumas classes que eu uso para pesquisas longas em C #. Existem basicamente 6 classes (veja abaixo).
fonte
Este é um belo screencast de 5 minutos sobre como fazer pesquisas longas usando PHP e jQuery: http://screenr.com/SNH
O código é bastante semelhante ao exemplo do dbr acima.
fonte
Aqui está um exemplo simples de pesquisa longa em PHP por Erik Dubbelboer usando o
Content-type: multipart/x-mixed-replace
cabeçalho:E aqui está uma demonstração:
http://dubbelboer.com/multipart.php
fonte
Eu usei isso para entender o Comet, também configurei o Comet usando o servidor Java Glassfish e encontrei muitos outros exemplos assinando o comdaily.com
fonte
Dê uma olhada nesta postagem do blog que possui código para um aplicativo de bate-papo simples em Python / Django / gevent .
fonte
Abaixo está uma longa solução de pesquisa que desenvolvi para o Inform8 Web. Basicamente, você substitui a classe e implementa o método loadData. Quando o loadData retorna um valor ou a operação atinge o tempo limite, imprimirá o resultado e o retorno.
Se o processamento do seu script demorar mais de 30 segundos, talvez você precise alterar a chamada set_time_limit () para algo mais longo.
Licença Apache 2.0. Versão mais recente no github https://github.com/ryanhend/Inform8/blob/master/Inform8-web/src/config/lib/Inform8/longpoll/LongPoller.php
Ryan
fonte
Obrigado pelo código, dbr . Apenas um pequeno erro de digitação em long_poller.htm ao redor da linha
Eu acho que deveria ser
para que funcione.
Para os interessados, tentei um equivalente ao Django. Inicie um novo projeto Django, digamos lp para pesquisas longas:
Ligue para o aplicativo msgsrv para o servidor de mensagens:
Adicione as seguintes linhas ao settings.py para ter um diretório de modelos :
Defina seus padrões de URL em urls.py da seguinte maneira:
E o msgsrv / views.py deve se parecer com:
Por fim, templates / long_poller.htm deve ser o mesmo que acima, com o erro de digitação corrigido. Espero que isto ajude.
fonte
"15000"
é o erro de sintaxe. setTimeout aceita um número inteiro como seu segundo parâmetro.Este é um dos cenários para os quais o PHP é uma péssima escolha. Como mencionado anteriormente, você pode amarrar todos os seus funcionários do Apache rapidamente, fazendo algo assim. O PHP foi criado para iniciar, executar, parar. Não foi construído para começar, espere ... execute, pare. Você atolará o servidor muito rapidamente e descobrirá que tem problemas incríveis de dimensionamento.
Dito isto, você ainda pode fazer isso com PHP e não matar seu servidor usando o nginx HttpPushStreamModule: http://wiki.nginx.org/HttpPushStreamModule
Você configura o nginx na frente do Apache (ou qualquer outra coisa) e ele se encarregará de manter abertas as conexões simultâneas. Você apenas responde com carga útil enviando dados para um endereço interno, o que você poderia fazer com um trabalho em segundo plano ou apenas enviar as mensagens para as pessoas que estavam esperando sempre que as novas solicitações chegavam. Isso impede que os processos PHP fiquem abertos durante uma longa pesquisa.
Isso não é exclusivo do PHP e pode ser feito usando o nginx com qualquer linguagem de back-end. O carregamento simultâneo de conexões abertas é igual ao Node.js, portanto, a maior vantagem é que ele o tira do NECESSIDADE de Nó para algo assim.
Você vê muitas outras pessoas mencionando outras bibliotecas de idiomas para realizar pesquisas longas e isso é por uma boa razão. O PHP simplesmente não está bem construído para esse tipo de comportamento naturalmente.
fonte
Por que não considerar os soquetes da Web em vez de pesquisas longas? Eles são muito eficientes e fáceis de configurar. No entanto, eles são suportados apenas em navegadores modernos. Aqui está uma referência rápida .
fonte
O grupo WS-I publicou algo chamado "Perfil Seguro Confiável" que possui uma implementação Glass Fish e .NET que aparentemente interopera bem.
Com alguma sorte existe um Javascript implementação de por aí também.
Há também uma implementação do Silverlight que usa HTTP Duplex. Você pode conectar o javascript ao Silverlight objeto para obter retornos de chamada quando ocorrer um push.
Também existem versões comerciais pagas também.
fonte
Para uma implementação do ASP.NET MVC, observe o SignalR que está disponível no NuGet . Observe que o NuGet geralmente está desatualizado da fonte Git, que é confirmada com muita frequência.
Leia mais sobre o SignalR em um blog de Scott Hanselman
fonte
Você pode experimentar o icomet ( https://github.com/ideawu/icomet ), um servidor cometa C1000K C ++ criado com libevent. O icomet também fornece uma biblioteca JavaScript, é fácil de usar tão simples quanto
O icomet suporta uma ampla variedade de navegadores e sistemas operacionais, incluindo Safari (iOS, Mac), IEs (Windows), Firefox, Chrome etc.
fonte
NodeJS mais simples
Cenário de produção no Express, por exemplo, você entraria
response
no middleware. Você faz o que precisa fazer, pode definir todos os métodos pesquisados há muito tempo para mapear ou algo do tipo (visível para outros fluxos) e chamar<Response> response.end()
sempre que estiver pronto. Não há nada de especial em conexões com sondagem longa. O resto é exatamente como você estrutura seu aplicativo.Se você não sabe o que quero dizer com escopo, isso deve lhe dar uma ideia
Como você vê, você pode realmente responder a todas as conexões, uma, fazer o que quiser. Há
id
todas as solicitações para que você possa usar o mapa e acessar chamadas específicas fora da API.fonte