C'est plus simple que je ne le pensais au départ. Fondamentalement, vous avez une page qui ne fait rien, jusqu'à ce que les données que vous souhaitez envoyer soient disponibles (par exemple, un nouveau message arrive).
Voici un exemple vraiment basique, qui envoie une chaîne simple au bout de 2 à 10 secondes. 1 chance sur 3 de retourner une erreur 404 (pour montrer la gestion des erreurs dans l'exemple Javascript à venir)
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));
?>
Remarque: Avec un site réel, l'exécuter sur un serveur Web ordinaire comme Apache bloquera rapidement tous les «threads de travail» et le laissera incapable de répondre à d'autres demandes. Il existe des moyens de contourner cela, mais il est recommandé d'écrire un "serveur à interrogation longue" dans quelque chose comme Python tordu , qui ne repose pas sur un thread par demande. cometD est populaire (disponible en plusieurs langues), et Tornado est un nouveau framework spécialement conçu pour ces tâches (il a été conçu pour le code de polling long de FriendFeed) ... mais à titre d'exemple simple, Apache est plus que suffisant ! Ce script pourrait facilement être écrit dans n'importe quelle langue (j'ai choisi Apache / PHP car ils sont très courants et je les ai exécutés localement)
Ensuite, en Javascript, vous demandez le fichier ci-dessus ( msg_srv.php
) et attendez une réponse. Lorsque vous en obtenez un, vous agissez sur les données. Ensuite, vous demandez le fichier et attendez à nouveau, agissez sur les données (et répétez)
Ce qui suit est un exemple d'une telle page. Lorsque la page est chargée, elle envoie la demande initiale pour le msgsrv.php
fichier. Si elle réussit, nous ajoutons le message à la #messages
div, puis après 1 seconde nous appelons à nouveau la fonction waitForMsg, ce qui déclenche l'attente.
La 1 seconde setTimeout()
est un limiteur de débit vraiment basique, cela fonctionne très bien sans cela, mais s'il revient msgsrv.php
toujours instantanément (avec une erreur de syntaxe, par exemple) - vous inondez le navigateur et il peut rapidement geler. Il serait préférable de vérifier si le fichier contient une réponse JSON valide et / ou de conserver un total cumulé de requêtes par minute / seconde, et de faire une pause appropriée.
Si la page fait une erreur, il ajoute l'erreur à la #messages
div, attend 15 secondes puis réessaye (identique à la façon dont nous attendons 1 seconde après chaque message)
La bonne chose à propos de cette approche est qu'elle est très résistante. Si la connexion Internet du client meurt, elle expirera, puis essayez de vous reconnecter - cela est inhérent à la durée de l'interrogation, aucune gestion d'erreur complexe n'est requise
Quoi qu'il en soit, le long_poller.htm
code, en utilisant le framework 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));
? pour ne rien faire, interroger la base de données tous les 100 milisecs? quand décide-t-il de mourir?J'ai un exemple de chat vraiment simple dans le cadre de slosh .
Edit : (puisque tout le monde colle son code ici)
Il s'agit du chat multi-utilisateurs complet basé sur JSON utilisant une interrogation longue et slosh . Ceci est une démonstration de la façon de faire les appels, veuillez donc ignorer les problèmes XSS. Personne ne devrait déployer cela sans le désinfecter au préalable.
Notez que le client a toujours une connexion au serveur, et dès que quelqu'un envoie un message, tout le monde devrait le voir à peu près instantanément.
la source
getNewComments
rappel là-bas, donc il le déclenche à la fin de chaque demande ajax sans finTornado est conçu pour les longues interrogations et comprend une application de discussion très minimale (quelques centaines de lignes de Python) dans / examples / chatdemo , y compris le code du serveur et le code du client JS. Cela fonctionne comme ceci:
Les clients utilisent JS pour demander des mises à jour car (numéro du dernier message), le serveur URLHandler les reçoit et ajoute un rappel pour répondre au client dans une file d'attente.
Lorsque le serveur reçoit un nouveau message, l'événement onmessage se déclenche, parcourt les rappels et envoie les messages.
Le JS côté client reçoit le message, l'ajoute à la page, puis demande des mises à jour depuis ce nouvel ID de message.
la source
Je pense que le client ressemble à une requête AJAX asynchrone normale, mais vous vous attendez à ce que cela prenne "longtemps" pour revenir.
Le serveur ressemble alors à ceci.
Ainsi, la demande AJAX va au serveur, incluant probablement un horodatage de la dernière mise à jour afin que vous
hasNewData()
sachiez quelles données vous avez déjà. Le serveur se trouve alors dans une boucle en veille jusqu'à ce que de nouvelles données soient disponibles. Pendant tout ce temps, votre demande AJAX est toujours connectée, suspendue juste en attente de données. Enfin, lorsque de nouvelles données sont disponibles, le serveur les transmet à votre requête AJAX et ferme la connexion.la source
Voici quelques classes que j'utilise pour les longues interrogations en C #. Il existe essentiellement 6 classes (voir ci-dessous).
la source
Ceci est un joli screencast de 5 minutes sur la façon de faire de longs sondages en utilisant PHP et jQuery: http://screenr.com/SNH
Le code est assez similaire à l'exemple de dbr ci-dessus.
la source
Voici un exemple simple d'interrogation longue en PHP par Erik Dubbelboer utilisant l'en-
Content-type: multipart/x-mixed-replace
tête:Et voici une démo:
http://dubbelboer.com/multipart.php
la source
J'ai utilisé ce pour se familiariser avec la comète, j'ai également mis en place Comet en utilisant le serveur Java Glassfish et a trouvé beaucoup d'autres exemples en vous inscrivant à cometdaily.com
la source
Jetez un œil à cet article de blog qui contient du code pour une application de chat simple en Python / Django / gevent .
la source
Voici une longue solution d'interrogation que j'ai développée pour Inform8 Web. Fondamentalement, vous remplacez la classe et implémentez la méthode loadData. Lorsque le loadData renvoie une valeur ou que l'opération expire, il imprime le résultat et retourne.
Si le traitement de votre script peut prendre plus de 30 secondes, vous devrez peut-être modifier l'appel set_time_limit () en quelque chose de plus long.
Licence Apache 2.0. Dernière version sur github https://github.com/ryanhend/Inform8/blob/master/Inform8-web/src/config/lib/Inform8/longpoll/LongPoller.php
Ryan
la source
Merci pour le code, dbr . Juste une petite faute de frappe dans long_poller.htm autour de la ligne
Je pense que ça devrait être
pour que cela fonctionne.
Pour ceux qui sont intéressés, j'ai essayé un équivalent Django. Démarrez un nouveau projet Django, dites lp pour une longue interrogation:
Appelez l'application msgsrv pour le serveur de messages:
Ajoutez les lignes suivantes à settings.py pour avoir un répertoire de modèles :
Définissez vos modèles d'URL dans urls.py comme tels:
Et msgsrv / views.py devrait ressembler à:
Enfin, templates / long_poller.htm devrait être le même que ci-dessus avec une faute de frappe corrigée. J'espère que cela t'aides.
la source
"15000"
c'est l'erreur de syntaxe. setTimeout prend un entier comme deuxième paramètre.C'est l'un des scénarios pour lesquels PHP est un très mauvais choix. Comme mentionné précédemment, vous pouvez attacher très rapidement tous vos employés Apache en faisant quelque chose comme ça. PHP est conçu pour démarrer, exécuter, arrêter. Il n'est pas conçu pour démarrer, attendre ... exécuter, arrêter. Vous enlèverez votre serveur très rapidement et découvrirez que vous avez des problèmes de mise à l'échelle incroyables.
Cela dit, vous pouvez toujours le faire avec PHP et ne pas tuer votre serveur en utilisant le nginx HttpPushStreamModule: http://wiki.nginx.org/HttpPushStreamModule
Vous configurez nginx devant Apache (ou quoi que ce soit d'autre) et il se chargera de maintenir ouvertes les connexions simultanées. Vous répondez simplement avec une charge utile en envoyant des données à une adresse interne que vous pourriez faire avec un travail en arrière-plan ou en envoyant simplement les messages aux personnes qui attendaient chaque fois que les nouvelles demandes arrivaient. Cela empêche les processus PHP de rester ouverts pendant une longue interrogation.
Ceci n'est pas exclusif à PHP et peut être fait en utilisant nginx avec n'importe quel langage backend. La charge des connexions ouvertes simultanées est égale à Node.js, donc le plus grand avantage est qu'il vous permet de sortir de NEDING Node pour quelque chose comme ça.
Vous voyez beaucoup d'autres personnes mentionner d'autres bibliothèques de langues pour avoir effectué un long sondage et c'est pour une bonne raison. PHP n'est tout simplement pas bien conçu pour ce type de comportement naturellement.
la source
Pourquoi ne pas envisager les sockets Web au lieu de longues interrogations? Ils sont très efficaces et faciles à installer. Cependant, ils ne sont pris en charge que dans les navigateurs modernes. Voici une référence rapide .
la source
Le groupe WS-I a publié quelque chose appelé "Reliable Secure Profile" qui a une implémentation de Glass Fish et .NET qui interagit apparemment bien.
Avec un peu de chance, il existe également une implémentation Javascript .
Il existe également une implémentation Silverlight qui utilise HTTP Duplex. Vous pouvez connecter javascript à l' objet Silverlight pour obtenir des rappels lorsqu'un push se produit.
Il existe également des versions commerciales payantes .
la source
Pour une implémentation ASP.NET MVC, regardez SignalR qui est disponible sur NuGet .. notez que le NuGet est souvent obsolète de la source Git qui obtient des commits très fréquents.
En savoir plus sur SignalR sur un blog de Scott Hanselman
la source
Vous pouvez essayer icomet ( https://github.com/ideawu/icomet ), un serveur de comète C1000K C ++ construit avec libevent. icomet fournit également une bibliothèque JavaScript, il est facile à utiliser aussi simple que
icomet prend en charge une large gamme de navigateurs et de systèmes d'exploitation, y compris Safari (iOS, Mac), IE (Windows), Firefox, Chrome, etc.
la source
NodeJS le plus simple
Scénario de production dans Express pour exmaple que vous obtiendriez
response
dans le middleware. Faites-vous ce que vous devez faire, pouvez étendre toutes les méthodes d'interrogation longues pour mapper ou quelque chose (qui est visible pour les autres flux), et invoquer<Response> response.end()
chaque fois que vous êtes prêt. Les connexions longues interrogées n'ont rien de spécial. Le reste est juste la façon dont vous structurez normalement votre application.Si vous ne savez pas ce que je veux dire par délimitation, cela devrait vous donner une idée
Comme vous le voyez, vous pouvez vraiment répondre à toutes les connexions, un, faites ce que vous voulez. Il y en a
id
pour chaque demande, vous devriez donc pouvoir utiliser la carte et accéder à des appels spécifiques hors api.la source