Zeigen Sie das Ergebnis auf der Webseite an, sobald die Daten auf dem Server verfügbar sind

8

Ich schreibe eine CGI-Seite in Python. Angenommen, ein Client sendet eine Anfrage an meine CGI-Seite. Meine CGI-Seite führt die Berechnung aus und sobald sie die erste Ausgabe hat, sendet sie diese Ausgabe an den Client zurück, aber es wird WEITER ausgeführt, um die Berechnung auszuführen und andere Antworten zu senden NACH stark> die erste Antwort wird gesendet.

Ist das, was ich hier vorgestellt habe, möglich? Ich stelle diese Frage, weil in meinem begrenzten Wissen, in einer CGI-Seite Antworten auf einmal Basic zurückgesendet werden, sobald eine Antwort gesendet wird, hört CGI-Seite auf zu laufen. Diese Sache ist auf der Serverseite oder Clientseite gemacht, und wie implementiere ich es?

Auf meinem Server läuft Apache. Vielen Dank.

Ich habe einen Client-Code von "dbr" in diesem Forum ausprobiert (dank ihm habe ich die Idee, wie lang-polling funktioniert).

%Vor%

Und hier ist mein Servercode:

%Vor%

Ich erwarte, dass auf meiner Clientseite jeweils 1 Zahl angezeigt wird (0,1,2, ...), aber die Daten werden immer auf einmal ausgegeben (01234 ...). Bitte hilf mir, es herauszufinden. Danke euch so sehr.

Nur ein bisschen out-track, ich versuche, jquery comet plugin zu verwenden, aber ich konnte keine ausreichende Dokumentation finden. Hilfen würden sehr geschätzt werden. Nochmals vielen Dank: D

[Bearbeiten] Ok Leute, schließlich habe ich es dank Eurer Guides geschafft, es zum Laufen zu bringen. Du hast recht, wenn du vorhersagst, dass mod_deflate die Quelle für all das ist.

Um es zusammenzufassen, was ich hier gemacht habe:

  • Erstellen Sie für den Client eine lange Abstimmungsseite als HTML-Code über

  • Deaktivieren Sie für den Server mod_deflate, indem Sie die Datei /etc/apache2/mods-available/deflate.conf bearbeiten, die Zeile mit dem text / html-Teil auskommentieren und den Server neu starten. Um sicherzustellen, dass Python die Ausgabe nicht selbst puffert, fügen Sie #! / Usr / bin / python -u am Anfang der Seite ein. Denken Sie daran, sys.stdout.flush () nach jedem Drucken zu verwenden, das auf dem Client angezeigt werden soll. Der Effekt ist möglicherweise nicht transparent und sollte time.sleep (1) zum Testen enthalten. : D

Danke euch sehr, dass ihr das unterstützt und unterstützt habt: D

    
wakandan 09.12.2009, 13:00
quelle

4 Antworten

8

Sicher.

Es gibt einen traditionellen servergesteuerten Ansatz, bei dem das Skript nur einmal ausgeführt wird, aber eine lange Zeit braucht, um die Seiten auszugeben, während es läuft:

%Vor%

Wenn Sie eine App in WSGI schreiben, geschieht dies dadurch, dass die Anwendung eine iterierbare Zahl zurückgibt, die jeden Block, der einzeln gesendet werden soll, einzeln ausgibt. Ich würde wirklich empfehlen, an WSGI zu schreiben; Sie können sie jetzt über CGI bereitstellen, aber in Zukunft, wenn Ihre App eine bessere Leistung benötigt, können Sie sie über einen schnelleren Server / eine schnellere Schnittstelle bereitstellen, ohne sie neu schreiben zu müssen.

WSGI-über-CGI-Beispiel:

%Vor%

Beachten Sie, dass Ihr Webserver diesen Ansatz (für CGI oder WSGI) durch Hinzufügen einer eigenen Pufferung vereiteln kann. Dies tritt normalerweise auf, wenn Sie output-transformierende Filter wie mod_deflate verwenden, um die Webapp-Ausgabe automatisch zu komprimieren. Sie müssen die Komprimierung für Skripts mit Teilantwort deaktivieren.

Dies beschränkt Sie darauf, die Seite Bit für Bit neu zu rendern, wenn neue Daten eintreffen. Sie können es hübscher machen, indem Sie die Seite des Clients veranlassen, die Seite zu ändern, wenn neue Daten eintreffen, zB.:

%Vor%

Dies beruht auf clientseitigem Skripting, so dass es eine gute Idee ist, eine nicht-scriptbasierte endgültige Ausgabe am Ende hinzuzufügen.

Währenddessen scheint die Seite immer noch geladen zu sein. Wenn Sie das nicht möchten, müssen Sie das Skript in eine erste Anfrage aufteilen, die nur den statischen Inhalt ausspuckt, einschließlich des clientseitigen Skripts, das mit dem Server entweder mit einer XMLHttpRequest-Abfrage nach neuen Daten sucht durch, oder, für die wirklich lang andauernden Fälle, viele XMLHttpRequests, von denen jeder den Status und alle neuen Daten zurückgibt. Dieser Ansatz ist viel komplizierter, da Sie Ihren Arbeitsprozess als Hintergrund-Daemon-Prozess neben dem Webserver ausführen müssen und Daten zwischen dem Daemon und der Front-End-CGI / WSGI-Anforderung übergeben müssen, indem Sie z. Pipes oder eine Datenbank.

    
bobince 09.12.2009, 14:04
quelle
1

Ja das ist möglich und du hast nicht viel getan, Wenn Sie Daten ausdrucken, wird der Server sie senden, nur um sicher zu sein, halten Sie stdout

    
Anurag Uniyal 09.12.2009 13:17
quelle
1

Es gibt ein paar Techniken.

Die altmodische Methode besteht darin, Daten weiter zu streamen und den Browser weiterhin mit progressivem Rendering rendern zu lassen. Also, als altmodisches CGI, mach einfach sys.stdout.flush() . Dies zeigt eine teilweise Seite, die Sie hinzufügen können, aber es sieht im Browser plump aus, weil der Throbber sich weiter dreht und es so aussieht, als ob der Server hängt oder überlastet ist.

Einige Browser unterstützen einen speziellen mehrteiligen MIME-Typ multipart/x-mixed-replace , mit dem Sie die Verbindung weiterhin öffnen können, aber der Browser ersetzt die Seite vollständig, wenn Sie den nächsten multipart Chunk senden (der MIME-formatiert sein muss). . Ich weiß nicht, ob das verwendbar ist - Internet Explorer unterstützt es nicht und es funktioniert möglicherweise auch nicht gut in anderen Browsern.

Der nächste moderne Weg besteht darin, den Server nach Ergebnissen mit Javascript XMLHttpRequest abzufragen. Dies erfordert, dass Sie die Ergebnisse der Operation von einem anderen Webserver-Thread oder -Prozess aus überprüfen können, was im serverseitigen Code etwas schwieriger zu erreichen sein kann. Es ermöglicht Ihnen jedoch, eine viel schönere Webseite zu erstellen.

Wenn Sie noch komplizierter werden möchten, schauen Sie sich das "Comet" -Modell oder "Web Sockets" an.

    
Mauve 09.12.2009 13:35
quelle
1

Der Trick in altmodischen CGI -Programmen verwendet die Transfer-Encoding: chunked HTTP-Header:

  

3.6.1 Chunked Transfer-Codierung

     

Die Chunked-Codierung ändert den Hauptteil einer Nachricht, um sie als eine Reihe von Chunks zu übertragen, jede mit ihrem eigenen Größenindikator, gefolgt von einem OPTIONAL-Trailer, der Entity-Header-Felder enthält. Dies ermöglicht, dass dynamisch erzeugter Inhalt zusammen mit den Informationen übertragen wird, die der Empfänger benötigt, um zu verifizieren, dass er die vollständige Nachricht erhalten hat.

Wenn ein Ergebnis verfügbar ist, senden Sie es als separaten Chunk - der Browser zeigt diese eigenständige HTTP-Nachricht an. Wenn ein weiterer Chunk später ankommt, wird NEW PAGE angezeigt.

Sie müssen die richtigen Header für jeden Chunk im Programm CGI erstellen. Denken Sie auch daran, die Ausgabe CGI am Ende jedes Chunks zu löschen. In Python geschieht dies mit sys.stdout .flush()

    
gimel 09.12.2009 14:04
quelle

Tags und Links