
dbr
Ich kann viele Informationen darüber finden, wie Long Polling funktioniert (z. B. Dasund Das), aber nein einfach Beispiele dafür, wie dies im Code implementiert wird.
Alles, was ich finden kann, ist Kometdas auf dem Dojo JS-Framework basiert, und einem ziemlich komplexen Serversystem.
Wie würde ich im Grunde Apache verwenden, um die Anforderungen zu bedienen, und wie würde ich ein einfaches Skript schreiben (z. B. in PHP), das den Server nach neuen Nachrichten “lang abfragt”?
Das Beispiel muss nicht skalierbar, sicher oder vollständig sein, es muss nur funktionieren!

dbr
Es ist einfacher, als ich anfangs dachte. Im Grunde haben Sie eine Seite, die nichts tut, bis die Daten, die Sie senden möchten, verfügbar sind (sagen wir, eine neue Nachricht kommt).
Hier ist ein wirklich einfaches Beispiel, das nach 2-10 Sekunden einen einfachen String sendet. Wahrscheinlichkeit von 1 zu 3, einen Fehler 404 zurückzugeben (um die Fehlerbehandlung im kommenden Javascript-Beispiel zu zeigen)
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));
?>
Hinweis: Wenn Sie eine echte Site auf einem normalen Webserver wie Apache ausführen, werden schnell alle “Worker-Threads” blockiert und sie kann nicht auf andere Anfragen reagieren. Es gibt Möglichkeiten, dies zu umgehen, aber es wird empfohlen, zu schreiben ein “Long-Poll-Server” in etwas wie dem von Python verdrehtedie nicht auf einen Thread pro Anfrage angewiesen ist. KometD ist ein beliebtes (das in mehreren Sprachen verfügbar ist) und Tornado ist ein neues Framework, das speziell für solche Aufgaben entwickelt wurde (es wurde für den Long-Polling-Code von FriendFeed entwickelt) … aber als einfaches Beispiel ist Apache mehr als ausreichend! Dieses Skript könnte leicht in jeder Sprache geschrieben werden (ich habe Apache/PHP gewählt, da sie sehr verbreitet sind und ich sie zufällig lokal ausgeführt habe).
Dann fordern Sie in Javascript die obige Datei an (msg_srv.php
) und auf eine Antwort warten. Wenn Sie eine erhalten, handeln Sie anhand der Daten. Dann fordern Sie die Datei an und warten erneut, handeln nach den Daten (und wiederholen)
Was folgt, ist ein Beispiel für eine solche Seite. Wenn die Seite geladen wird, sendet sie die erste Anfrage für die msgsrv.php
file.. Wenn es erfolgreich ist, hängen wir die Nachricht an die an #messages
div, dann rufen wir nach 1 Sekunde erneut die Funktion waitForMsg auf, die das Warten auslöst.
Die 1 Sekunde setTimeout()
ist ein wirklich einfacher Ratenbegrenzer, es funktioniert gut ohne diesen, aber wenn msgsrv.php
immer kehrt sofort zurück (z. B. mit einem Syntaxfehler) – Sie überfluten den Browser und er kann schnell einfrieren. Dies sollte besser durchgeführt werden, indem überprüft wird, ob die Datei eine gültige JSON-Antwort enthält, und/oder eine laufende Summe der Anforderungen pro Minute/Sekunde beibehalten und entsprechend angehalten wird.
Wenn die Seite fehlerhaft ist, wird der Fehler an die angehängt #messages
div, wartet 15 Sekunden und versucht es dann erneut (identisch wie wir 1 Sekunde nach jeder Nachricht warten)
Das Schöne an diesem Ansatz ist, dass er sehr belastbar ist. Wenn die Internetverbindung des Clients unterbrochen wird, kommt es zu einer Zeitüberschreitung. Versuchen Sie dann, die Verbindung erneut herzustellen – dies hängt davon ab, wie lange die Abfrage funktioniert, es ist keine komplizierte Fehlerbehandlung erforderlich
Jedenfalls die long_poller.htm
Code unter Verwendung des jQuery-Frameworks:
<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>

Dustin
Ich habe ein wirklich einfaches Chat-Beispiel als Teil von schwappen.
Bearbeiten: (da jeder hier seinen Code einfügt)
Dies ist der vollständige JSON-basierte Multi-User-Chat mit Long-Polling und schwappen. Das ist ein Demo wie die Aufrufe durchzuführen sind, also ignorieren Sie bitte die XSS-Probleme. Niemand sollte dies bereitstellen, ohne es vorher zu desinfizieren.
Beachten Sie, dass der Client immer hat eine Verbindung zum Server, und sobald jemand eine Nachricht sendet, sollte jeder sie ungefähr sofort sehen.
<?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>

mikemaccana
Tornado ist für Long-Polling konzipiert und enthält ein sehr minimales (wenige hundert Zeilen Python) Chat-App in /Beispiele/Chatdemo , einschließlich Servercode und JS-Clientcode. Es funktioniert so:
-
Clients verwenden JS, um nach Aktualisierungen seit (Nummer der letzten Nachricht) zu fragen, der Server URLHandler empfängt diese und fügt einen Rückruf hinzu, um dem Client in einer Warteschlange zu antworten.
-
Wenn der Server eine neue Nachricht erhält, wird das Ereignis onmessage ausgelöst, durchläuft die Rückrufe und sendet die Nachrichten.
-
Das clientseitige JS empfängt die Nachricht, fügt sie der Seite hinzu und fragt dann nach Aktualisierungen seit dieser neuen Nachrichten-ID.
Ich denke, der Client sieht aus wie eine normale asynchrone AJAX-Anfrage, aber Sie erwarten, dass es “lange” dauert, bis er zurückkommt.
Der Server sieht dann so aus.
while (!hasNewData())
usleep(50);
outputNewData();
Die AJAX-Anfrage geht also an den Server, wahrscheinlich einschließlich eines Zeitstempels der letzten Aktualisierung, damit Ihre hasNewData()
weiß, welche Daten Sie bereits haben. Der Server befindet sich dann in einer Schleife und schläft, bis neue Daten verfügbar sind. Währenddessen ist Ihre AJAX-Anfrage immer noch verbunden und wartet nur auf Daten. Wenn schließlich neue Daten verfügbar sind, gibt der Server diese an Ihre AJAX-Anfrage weiter und schließt die Verbindung.

Gefangener NULL
Hier sind einige Klassen, die ich für Long-Polling in C# verwende. Es gibt grundsätzlich 6 Klassen (siehe unten).
- Regler: Verarbeitet Aktionen, die zum Erstellen einer gültigen Antwort erforderlich sind (Datenbankoperationen usw.)
- Prozessor: Verwaltet die asynchrone Kommunikation mit der Webseite (selbst)
- IAsynchProcessor: Der Dienst verarbeitet Instanzen, die diese Schnittstelle implementieren
- Dienst: Verarbeitet Anforderungsobjekte, die IAsynchProcessor implementieren
- Anfrage: Der IAsynchProcessor-Wrapper, der Ihre Antwort enthält (Objekt)
- Antwort: Enthält benutzerdefinierte Objekte oder Felder

Sean O
Dies ist ein netter 5-minütiger Screencast darüber, wie man lange Abfragen mit PHP und jQuery durchführt:
http://screenr.com/SNH
Code ist ziemlich ähnlich zu dbrBeispiel oben.

dbr
Hier ist ein einfaches Long-Polling-Beispiel in PHP von Erik Dubbelboer Verwendung der Content-type: multipart/x-mixed-replace
Header:
<?
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
';
Und hier ist eine Demo:
http://dubbelboer.com/multipart.php
9933900cookie-checkWie implementiere ich grundlegendes „Long Polling“?yes