Question Comment puis-je implémenter "Long Polling" de base?


Je peux trouver beaucoup d'informations sur le fonctionnement du sondage de longue durée (par exemple, ce, et ce), mais non simple des exemples de la façon de l'implémenter dans le code.

Tout ce que je peux trouver est cometd, qui repose sur le framework Dojo JS, et un système de serveur assez complexe.

Fondamentalement, comment pourrais-je utiliser Apache pour servir les requêtes, et comment j'écrirais un script simple (disons, en PHP) qui "interrogerait" le serveur à la recherche de nouveaux messages?

L'exemple ne doit pas nécessairement être évolutif, sécurisé ou complet, il suffit de travailler!


744
2017-12-02 11:14


origine


Réponses:


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 voulez envoyer soient disponibles (par exemple, un nouveau message arrive).

Voici un exemple vraiment basique, qui envoie une chaîne simple après 2 à 10 secondes. 1 chance sur 3 de renvoyer 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));
?>

Note: Avec un site réel, l'exécuter sur un serveur web normal comme Apache va rapidement lier tous les "threads de travail" et le laisser incapable de répondre à d'autres requêtes. Il y a des façons de contourner cela, mais il est recommandé d'écrire un "serveur à long sondage" dans quelque chose comme Python tordu, qui ne repose pas sur un thread par requête. cometD est populaire (disponible en plusieurs langues), et Tornade est un nouveau framework spécialement conçu pour de telles tâches (il a été conçu pour le code d'interrogation longue de FriendFeed) ... mais comme un 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 communs, 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 encore, 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 .. S'il 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, ça marche bien sans cela, mais si msgsrv.php  toujours renvoie instantanément (avec une erreur de syntaxe, par exemple) - vous inonder le navigateur et il peut rapidement se bloquer. Il vaut mieux vérifier si le fichier contient une réponse JSON valide et / ou conserver un nombre total de demandes par minute / seconde, et mettre en pause de manière appropriée.

Si les erreurs de page, il ajoute l'erreur à la #messages div, attend 15 secondes puis réessaie (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ésiliente. Si la connexion Internet du client disparaît, elle expirera, puis tentera de se reconnecter, ce qui est inhérent à la durée de l'interrogation, sans manipulation compliquée des erreurs.

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>

491
2017-12-02 13:15



J'ai un exemple de chat très simple dans le cadre de patauger.

modifier: (puisque tout le monde colle leur code ici)

Ceci est le chat multi-utilisateur basé sur JSON complet en utilisant de longues interrogations et patauger. C'est un démo de la façon de faire les appels, alors s'il vous plaît ignorer les problèmes XSS. Personne ne devrait le déployer sans l'assainir d'abord.

Notez que le client toujours a une connexion au serveur, et dès que quelqu'un envoie un message, tout le monde devrait le voir à peu près instantanément.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2008 Dustin Sallings <dustin+html@spy.net> -->
<html lang="en">
  <head>
    <title>slosh chat</title>
    <script type="text/javascript"
      src="http://code.jquery.com/jquery-latest.js"></script>
    <link title="Default" rel="stylesheet" media="screen" href="style.css" />
  </head>

  <body>
    <h1>Welcome to Slosh Chat</h1>

    <div id="messages">
      <div>
        <span class="from">First!:</span>
        <span class="msg">Welcome to chat. Please don't hurt each other.</span>
      </div>
    </div>

    <form method="post" action="#">
      <div>Nick: <input id='from' type="text" name="from"/></div>
      <div>Message:</div>
      <div><textarea id='msg' name="msg"></textarea></div>
      <div><input type="submit" value="Say it" id="submit"/></div>
    </form>

    <script type="text/javascript">
      function gotData(json, st) {
        var msgs=$('#messages');
        $.each(json.res, function(idx, p) {
          var from = p.from[0]
          var msg = p.msg[0]
          msgs.append("<div><span class='from'>" + from + ":</span>" +
            " <span class='msg'>" + msg + "</span></div>");
        });
        // The jQuery wrapped msgs above does not work here.
        var msgs=document.getElementById("messages");
        msgs.scrollTop = msgs.scrollHeight;
      }

      function getNewComments() {
        $.getJSON('/topics/chat.json', gotData);
      }

      $(document).ready(function() {
        $(document).ajaxStop(getNewComments);
        $("form").submit(function() {
          $.post('/topics/chat', $('form').serialize());
          return false;
        });
        getNewComments();
      });
    </script>
  </body>
</html>

41
2017-12-03 21:08



Tornade est conçu pour une longue interrogation, et comprend un très minime (quelques centaines de lignes de Python) application de chat dans /exemples / chatdemo , y compris le code du serveur et le code client JS. Cela fonctionne comme ceci:

  • Les clients utilisent JS pour demander des mises à jour depuis (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, boucle 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.


31
2018-03-04 14:53



Je pense que le client ressemble à une requête AJAX asynchrone normale, mais vous vous attendez à ce que cela prenne "beaucoup de temps" pour revenir.

Le serveur ressemble alors à ceci.

while (!hasNewData())
    usleep(50);

outputNewData();

Ainsi, la requête AJAX va au serveur, incluant probablement un horodatage de la dernière mise à jour pour que votre hasNewData() sait quelles données vous avez déjà. Le serveur reste alors dans une boucle en veille jusqu'à ce que de nouvelles données soient disponibles. Pendant tout ce temps, votre requête AJAX est toujours connectée, juste en attente de données. Enfin, lorsque de nouvelles données sont disponibles, le serveur le donne à votre requête AJAX et ferme la connexion.


24
2017-12-02 11:39



Ici Certaines classes sont utilisées pour les longues interrogations en C #. Il y a fondamentalement 6 classes (voir ci-dessous).

  1. Manette: Traite les actions requises pour créer une réponse valide (opérations db etc.)
  2. Processeur: Gère la communication asynch avec la page Web (elle-même)
  3. IAsynchProcessor: Le service traite les instances qui implémentent cette interface
  4. Sevice: Traite les objets de requête qui implémentent IAsynchProcessor
  5. Demande: Le wrapper IAsynchProcessor contenant votre réponse (objet)
  6. Réponse: Contient des objets ou des champs personnalisés

17
2017-09-01 14:20



Ceci est un bon screencast de 5 minutes sur la façon de faire une longue interrogation en utilisant PHP et jQuery: http://screenr.com/SNH

Code est assez similaire à dbrl'exemple ci-dessus.


16
2017-10-20 15:41



Voici un exemple simple d'interrogation en PHP par Erik Dubbelboer en utilisant le Content-type: multipart/x-mixed-replace entête:

<?

header('Content-type: multipart/x-mixed-replace; boundary=endofsection');

// Keep in mind that the empty line is important to separate the headers
// from the content.
echo 'Content-type: text/plain

After 5 seconds this will go away and a cat will appear...
--endofsection
';
flush(); // Don't forget to flush the content to the browser.


sleep(5);


echo 'Content-type: image/jpg

';

$stream = fopen('cat.jpg', 'rb');
fpassthru($stream);
fclose($stream);

echo '
--endofsection
';

Et voici une démo:

http://dubbelboer.com/multipart.php


12
2017-12-08 12:23



j'ai utilisé ce Pour se familiariser avec Comet, j'ai également mis en place Comet en utilisant le serveur Java Glassfish et trouvé beaucoup d'autres exemples en m'abonnant à cometdaily.com


11
2017-12-02 11:21