Es más simple de lo que pensé inicialmente. Básicamente, tiene una página que no hace nada, hasta que los datos que desea enviar estén disponibles (por ejemplo, llega un nuevo mensaje).
Aquí hay un ejemplo realmente básico, que envía una cadena simple después de 2-10 segundos. 1 de cada 3 posibilidades de devolver un error 404 (para mostrar el manejo de errores en el próximo ejemplo 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: con un sitio real, ejecutar esto en un servidor web normal como Apache vinculará rápidamente todos los "subprocesos de trabajo" y dejará que no pueda responder a otras solicitudes. Hay formas de evitar esto, pero se recomienda escribir un "servidor de sondeo largo" en algo como Python torcido , que no se basa en un hilo por solicitud. cometD es popular (que está disponible en varios idiomas), y Tornado es un nuevo marco creado específicamente para tales tareas (fue construido para el código de sondeo largo de FriendFeed) ... pero como un simple ejemplo, Apache es más que adecuado ! Este script podría escribirse fácilmente en cualquier idioma (elegí Apache / PHP, ya que son muy comunes, y resultó que los ejecutaba localmente)
Luego, en Javascript, solicita el archivo anterior ( msg_srv.php
) y espera una respuesta. Cuando obtienes uno, actúas sobre los datos. Luego solicita el archivo y espera nuevamente, actúa sobre los datos (y repite)
Lo que sigue es un ejemplo de dicha página ... Cuando se carga la página, envía la solicitud inicial del msgsrv.php
archivo ... Si tiene éxito, agregamos el mensaje al #messages
div, luego de 1 segundo llamamos a la función waitForMsg nuevamente, lo que desencadena la espera.
El 1 segundo setTimeout()
es un limitador de velocidad realmente básico, funciona bien sin esto, pero si msgsrv.php
siempre regresa instantáneamente (con un error de sintaxis, por ejemplo): inunda el navegador y puede congelarse rápidamente. Será mejor que verifique si el archivo contiene una respuesta JSON válida y / o mantenga un total acumulado de solicitudes por minuto / segundo, y pause adecuadamente.
Si la página falla, agrega el error al #messages
div, espera 15 segundos y luego lo intenta nuevamente (idéntico a cómo esperamos 1 segundo después de cada mensaje)
Lo bueno de este enfoque es que es muy resistente. Si la conexión a Internet del cliente se corta, se agota el tiempo de espera, luego intenta volver a conectarse; esto es inherente a la duración del sondeo, no se requiere un manejo de errores complicado
De todos modos, el long_poller.htm
código, usando el marco 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 no hacer nada, sondear la base de datos cada 100 milisegundos? cuando decide morir?Tengo un ejemplo de chat realmente simple como parte de slosh .
Editar : (ya que todos están pegando su código aquí)
Este es el chat multiusuario completo basado en JSON que utiliza sondeos largos y slosh . Esta es una demostración de cómo hacer las llamadas, así que ignore los problemas de XSS. Nadie debería implementar esto sin desinfectarlo primero.
Tenga en cuenta que el cliente siempre tiene una conexión con el servidor, y tan pronto como alguien envíe un mensaje, todos deberían verlo de manera aproximada al instante.
fuente
getNewComments
devolución de llamada allí, por lo que solo se dispara al final de cada solicitud de ajax sin finTornado está diseñado para sondeos largos e incluye una aplicación de chat mínima (unos cientos de líneas de Python) en / examples / chatdemo , que incluye el código del servidor y el código del cliente JS. Funciona así:
Los clientes usan JS para solicitar actualizaciones ya que (número del último mensaje), el servidor URLHandler las recibe y agrega una devolución de llamada para responder al cliente a una cola.
Cuando el servidor recibe un nuevo mensaje, se activa el evento onmessage, recorre las devoluciones de llamada y envía los mensajes.
El JS del lado del cliente recibe el mensaje, lo agrega a la página y luego solicita actualizaciones desde este nuevo ID de mensaje.
fuente
Creo que el cliente parece una solicitud AJAX asíncrona normal, pero se espera que tarde "mucho tiempo" en volver.
El servidor se ve así.
Por lo tanto, la solicitud de AJAX va al servidor, probablemente incluyendo una marca de tiempo de cuándo fue la última actualización para que
hasNewData()
sepa qué datos ya tiene. El servidor se queda en un bucle de espera hasta que haya nuevos datos disponibles. Todo el tiempo, su solicitud AJAX todavía está conectada, simplemente colgando allí esperando datos. Finalmente, cuando hay nuevos datos disponibles, el servidor los entrega a su solicitud AJAX y cierra la conexión.fuente
Aquí hay algunas clases que uso para encuestas largas en C #. Básicamente hay 6 clases (ver más abajo).
fuente
Este es un buen screencast de 5 minutos sobre cómo hacer encuestas largas usando PHP y jQuery: http://screenr.com/SNH
El código es bastante similar al ejemplo anterior de dbr .
fuente
Aquí hay un ejemplo simple de sondeo largo en PHP de Erik Dubbelboer usando el
Content-type: multipart/x-mixed-replace
encabezado:Y aquí hay una demostración:
http://dubbelboer.com/multipart.php
fuente
Utilicé esto para familiarizarme con Comet, también configuré Comet usando el servidor Java Glassfish y encontré muchos otros ejemplos suscribiéndome a cometdaily.com
fuente
Eche un vistazo a esta publicación de blog que tiene código para una aplicación de chat simple en Python / Django / gevent .
fuente
A continuación se muestra una solución de sondeo larga que he desarrollado para Inform8 Web. Básicamente, anula la clase e implementa el método loadData. Cuando loadData devuelve un valor o la operación agota el tiempo de espera, imprimirá el resultado y regresará.
Si el procesamiento de su script puede demorar más de 30 segundos, es posible que deba modificar la llamada set_time_limit () a algo más largo.
Licencia de Apache 2.0. Última versión en github https://github.com/ryanhend/Inform8/blob/master/Inform8-web/src/config/lib/Inform8/longpoll/LongPoller.php
Ryan
fuente
Gracias por el código, dbr . Solo un pequeño error tipográfico en long_poller.htm alrededor de la línea
Creo que debería ser
para que funcione
Para aquellos interesados, probé un equivalente de Django. Comience un nuevo proyecto de Django, diga lp para encuestas largas:
Llame a la aplicación msgsrv para el servidor de mensajes:
Agregue las siguientes líneas a settings.py para tener un directorio de plantillas :
Defina sus patrones de URL en urls.py como tal:
Y msgsrv / views.py debería verse así:
Por último, templates / long_poller.htm debería ser el mismo que el anterior con error tipográfico corregido. Espero que esto ayude.
fuente
"15000"
es el error de sintaxis. setTimeout toma un número entero como su segundo parámetro.Este es uno de los escenarios para los que PHP es una muy mala elección. Como se mencionó anteriormente, puede vincular a todos sus trabajadores de Apache muy rápidamente haciendo algo como esto. PHP está construido para iniciar, ejecutar, detener. No está diseñado para comenzar, esperar ... ejecutar, detener. Atascará su servidor muy rápidamente y descubrirá que tiene problemas de escala increíbles.
Dicho esto, aún puede hacer esto con PHP y que no mate su servidor utilizando el nginx HttpPushStreamModule: http://wiki.nginx.org/HttpPushStreamModule
Configura nginx frente a Apache (o cualquier otra cosa) y se encargará de mantener abiertas las conexiones concurrentes. Simplemente responde con la carga útil enviando datos a una dirección interna que podría hacer con un trabajo en segundo plano o simplemente enviando los mensajes a las personas que estaban esperando cada vez que llegan las nuevas solicitudes. Esto evita que los procesos de PHP permanezcan abiertos durante largas encuestas.
Esto no es exclusivo de PHP y se puede hacer usando nginx con cualquier lenguaje de fondo. La carga de conexiones abiertas simultáneas es igual a Node.js, por lo que la mayor ventaja es que te saca de NADA NECESARIO para algo como esto.
Ves a muchas otras personas que mencionan otras bibliotecas de idiomas para lograr encuestas largas y eso es por una buena razón. PHP simplemente no está bien construido para este tipo de comportamiento, naturalmente.
fuente
¿Por qué no considerar las tomas web en lugar de las encuestas largas? Son mucho más eficientes y fáciles de configurar. Sin embargo, solo son compatibles con los navegadores modernos. Aquí hay una referencia rápida .
fuente
El grupo WS-I publicó algo llamado "Perfil seguro confiable" que tiene una implementación Glass Fish y .NET que aparentemente interactúan bien.
Con suerte hay un Javascript implementación de .
También hay una implementación de Silverlight que usa HTTP Duplex. Puede conectar javascript a Silverlight objeto para obtener devoluciones de llamada cuando se produce una inserción.
También hay versiones comerciales de pago también.
fuente
Para una implementación ASP.NET MVC, mire SignalR que está disponible en NuGet ... tenga en cuenta que NuGet a menudo está desactualizado de la fuente Git que recibe confirmaciones muy frecuentes.
Lea más sobre SignalR en un blog de Scott Hanselman
fuente
Puede probar icomet ( https://github.com/ideawu/icomet ), un servidor cometa C1000K C ++ construido con libevent. icomet también proporciona una biblioteca de JavaScript, es fácil de usar tan simple como
icomet admite una amplia gama de navegadores y sistemas operativos, incluidos Safari (iOS, Mac), IE (Windows), Firefox, Chrome, etc.
fuente
Nodo más simple JS
Escenario de producción inteligente en Express por ejemplo que obtendría
response
en el middleware. ¿Hace lo que necesita hacer, puede abarcar todos los métodos sondeados para asignar o algo (que es visible para otros flujos) e invocar<Response> response.end()
cuando esté listo. No hay nada especial en las conexiones sondeadas largas. El descanso es la forma en que normalmente estructura su aplicación.Si no sabes a qué me refiero con el alcance, esto debería darte una idea
Como puede ver, realmente podría responder a todas las conexiones, una, hacer lo que quiera. Hay
id
para cada solicitud, por lo que debería poder usar el mapa y acceder a llamadas específicas fuera de la API.fuente