Server im Http-Server ;)

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Hi,

Ich werde meine Frage anhand eines Chatservers als Beispiel erläutern.

Es sieht so aus: Ein Benutzer der Website hat eine seite geöffnet. Die website ist komplett in python programmiert, läuft jedoch unter einem HTTP-Server eurer wahl (zB mit fastcgi)

Hier die Herausforderung: Wenn ein Benutzer eine Chatnachricht sendet, soll diese automatisch an alle clients gebroadcastet werden.

Aktuelle Lösung: Es gibt einen externen server, mit dem sich jeder "Seitenaufruf" verbindet.

Lässt sich das Problem auch ohne zusätzliche Socket-Verbindung lösen? Kann man den Server also direkt im HTTP-Server impelemtieren? Es handelt sich ja im prinzip um eine Art Variablen-Sharing.
Zuletzt geändert von Jan.O am Freitag 16. Mai 2008, 22:05, insgesamt 1-mal geändert.
lunar

Jan.O hat geschrieben:Aktuelle Lösung: Es gibt einen externen server, mit dem sich jeder "Seitenaufruf" verbindet. Dann wird über einen socket an diese clients gebroadcasted.
HTTP unterstützt keine Push-Prozesse. Das wäre auch gar nicht möglich, da HTTP zustandslos ist und per definitionem keine Verbindung zum Client hält, nach dem der Response abgeschlossen ist. Alle Client müssen die Änderungen einer Website manuell(!) holen.

Entweder "fakst" du PUSH-Szenarien, indem du mit Javascript oder HTML-Meta-Refreshs die Seite periodisch neu lädst (was entsprechend hohe Serverlast zur Folge hat) oder du musst dir mit externen Technologien behelfen. Java-Applets, Flash-Programme, und mittlerweile auch Silverlight wären so Dinge, die man dafür (miss-)brauchen könnte. Ansonsten bleibt dir natürlich dein bisheriger Weg (den ich allerdings nicht ganz verstanden habe ;) )
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Es ist ohne Weiteres möglich die http-verbindung nach senden der HTML-Struktur aufrecht zu erhalten und nachträglich javascript-befehle im <script>-Tag nachzusenden. Getestet mit PHP in den IEs, FF und Opera.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

HTTP-Keep-Alive und asynchrones Pollen sind trotzdem noch kein Push.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Y0Gi hat geschrieben:HTTP-Keep-Alive und asynchrones Pollen sind trotzdem noch kein Push.
Ich spreche tatsächlich nicht von einer HTTP-Keep-Alive verbindung sondern von einer aufrechtgehaltenen Socketverbindung zwischen webserver und browser, was das nachträgliche senden von scriptbefehlen möglich macht.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Gehen tut das schon, aber schön und praktisch ist das nicht: http://dev.pocoo.org/hg/sandbox/file/10 ... ingchat.py
TUFKAB – the user formerly known as blackbird
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Hm, ich habe wohl zu lange Java gemacht, denn mein erster Implus bei Jan.Os Fragen ist immer, auf Java und die Möglichkeiten dort hinzuweisen. Wäre Flash & AMF eine Alternative? Dann wäre PyAMF vielleicht einen Blick wert. Schon aus dem Grund, als das mich das interessieren würde... Was allerdings auch nicht schlecht aussah, war Orbited.

Jedenfalls brauchst du wohl einen eigenen externen Server, da Python-Webrahmenwerke in der Regel ja Request-basiert ("share nothing") arbeiten und nicht aus einem Application Server (wie bei Java) arbeiten. Es gibt zwar mit CherryPy und Paste zwei Standalone-Server, doch sie werden irgendwie selten empfohlen, sodass ich hier das Vorurteil hätte, dass das nicht gut skaliert.

Und dann ist da natürlich noch Zope... verdammt, ich muss da dringend mehr drüber lernen, denn sagen kann ich dazu gar nichts, außer dass das ein Application Server wäre (Google nach Comet+Zope befragt gibt aber keine überzeugenden Hits).

Stefan
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich würde auch wohl als erstes mal Comet ausprobieren, muss zugeben, dass ich es noch nicht benutzt habe. Teilweise auch darum, weil Webchats sowieso eine kranke Idee sind.

Und ja, Zope skaliert nicht wirklich. Zumindest Zope 2 hat deutlich bessere Hardware gebraucht, um zu laufen, als normale Frameworks. Dafür bietet es auch mehr, zugegeben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Jan.O hat geschrieben:Ich spreche tatsächlich nicht von einer HTTP-Keep-Alive verbindung sondern von einer aufrechtgehaltenen Socketverbindung zwischen webserver und browser, was das nachträgliche senden von scriptbefehlen möglich macht.
Da habe ich mich wohl zu sehr an
Jan.O hat geschrieben:[...] an alle clients gebroadcastet werden, die gerade eine http-Verbindung aufrecht erhalten.
festgehalten. Wenn du natürlich parallel eine Socket-Verbindung aufbaust/aufrecht erhältst, hat das wenig (as in: nichts mehr) mit HTTP zu tun. Angesichts von HTTP-Proxies, Routern und (Personal) Firewalls dürfte so ein Ansatz in breiter Anwendung vermutlich zum Scheitern verurteilt sein, weil speziell auch der Browser mit sowas nicht umgehen kann oder will.
Ausnahmen sind hier Browser-Plugins mit Sandbox, wie ja schon genannt, eben Flash, ActiveX und Java. Bis auf Flash sehe ich da allerdings keine Zukunft; und heutzutage einen simplen Chat als Java-Applet unters Volk bringen zu wollen, erscheint mir schon fast irrwitzig.

Ich denke nicht, dass es eine Frage des Web-Frameworks auf Serverseite ist, sondern des/der eingesetzten Protokolls/e.

P.S.: Ich bin mal über einen Chat-PoC gestolpert, bei dem ein dynamisch erzeugtes PNG mit Chat-Nachrichten über eine aufrecht erhaltene Verbindung und längere Zeit zeilenweise an den Client geliefert wird, der es dann nach und nach anzeigt ;)
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Ersteinmal: Ich will keinen Chat programmieren. Ich beziehe mich nur auf das beispiel eines Chats, um das Problem besser darstellen zu können.
Y0Gi hat geschrieben:
Jan.O hat geschrieben:Ich spreche tatsächlich nicht von einer HTTP-Keep-Alive verbindung sondern von einer aufrechtgehaltenen Socketverbindung zwischen webserver und browser, was das nachträgliche senden von scriptbefehlen möglich macht.
Da habe ich mich wohl zu sehr an
Jan.O hat geschrieben:[...] an alle clients gebroadcastet werden, die gerade eine http-Verbindung aufrecht erhalten.
festgehalten. Wenn du natürlich parallel eine Socket-Verbindung aufbaust/aufrecht erhältst, hat das wenig (as in: nichts mehr) mit HTTP zu tun. Angesichts von HTTP-Proxies, Routern und (Personal) Firewalls dürfte so ein Ansatz in breiter Anwendung vermutlich zum Scheitern verurteilt sein, weil speziell auch der Browser mit sowas nicht umgehen kann oder will.
Ausnahmen sind hier Browser-Plugins mit Sandbox, wie ja schon genannt, eben Flash, ActiveX und Java. Bis auf Flash sehe ich da allerdings keine Zukunft; und heutzutage einen simplen Chat als Java-Applet unters Volk bringen zu wollen, erscheint mir schon fast irrwitzig.
Die HTTP-Verbindung ist ja auch nur eine Socket-Verbindung. Und ich spreche davon, DIESE aufrecht zu erhalten. Keep-Alive ist so ähnlich, allerdings ist der Transfer der Website normalerweise irgendwann abgeschlossen und es können keine weiteren daten mehr übermittelt werden.

Und das geht auch.
Jan.O hat geschrieben:Es ist ohne Weiteres möglich die http-verbindung nach senden der HTML-Struktur aufrecht zu erhalten und nachträglich javascript-befehle im <script>-Tag nachzusenden. Getestet mit PHP in den IEs, FF und Opera.
Das sind mehr als 98% aller Benutzer. Ich habe ohne probleme mehrere stunden lang script-befehle nachgesendet

@Leonidas Vielen Dank für den Tipp mit Comet! Werde ich mir mal angucken.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Leider habe ich nicht die leiseste Vorstellung von dem, was du mit "Script-Befehlen" meinst.

Hast du für das (wie ich es verstanden habe) nachträgliche Hijacken des HTTP-Sockets Beispielcode?
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Y0Gi hat geschrieben:Leider habe ich nicht die leiseste Vorstellung von dem, was du mit "Script-Befehlen" meinst.
Etwas in der Art eben:

Code: Alles auswählen

from time import sleep

def http_abuse(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    yield '<html><title>Tolle Seite</title><body>'
    while True:
        sleep(1)
        yield '<script>alert("I\'m still alive");</script>'
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ah! Das gehört dann aber doch noch zum selben und einzigen HTTP-Request?
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

.oO( Hat sich eigentlich irgendjemand mein Beispiel angesehen? )
TUFKAB – the user formerly known as blackbird
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

mitsuhiko hat geschrieben:.oO( Hat sich eigentlich irgendjemand mein Beispiel angesehen? )
Ja, und einen rudimentären IRC-Client damit gebaut -.-
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

mitsushiko: Ja, aber erst jetzt hab' ich's irgendwie verstanden.

Gibt es dabei irgendwelche Limitierungen*, z.B. kann diese Verbindung "unendlich lange" aufrecht erhalten werden?

Was genau macht Comet anders?

Gibt es bessere Ansätze? Scheinbar ja nicht ...


*) Ok, mal abgesehen davon, dass ich den Server hier abschießen muss und nicht mehr normal beenden kann.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Y0Gi hat geschrieben: Gibt es dabei irgendwelche Limitierungen*, z.B. kann diese Verbindung "unendlich lange" aufrecht erhalten werden?
Ja

Wäre cool, wenn sich noch mal jemand zur ursprünglichen Frage äußern könnte, wie ich jetzt daten an alle geöffneten http-clients broadcasten könnte
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Broadcasten in dem Sinne kann es ja schon nicht sein, da du zu jedem Client einen eigenen Socket hast.

Ich würde versuchen, die WSGI-Callable nach dem eigentlichen XHTML-Dokument weitere Daten aus einem Iterable holen zu lassen, das allen Instanzen zur Verfügung steht, entsprechend thread-safe sein müsste und aus dem pro Request/Socket jedes Element nur einmal gelesen wird. Notfalls könnte man für die aktiven Client-Verbindungen eine Liste von ``Queue``-Objekten bereithalten (was dann aber z.B. einen separaten Thread erfordert) und jedes bei vorliegenden Daten füttern, die der Client sich abholt.

Jan.O hat geschrieben:
Y0Gi hat geschrieben: Gibt es dabei irgendwelche Limitierungen*, z.B. kann diese Verbindung "unendlich lange" aufrecht erhalten werden?
Ja
Dann kannst du sie mir ja auch kurz ausführen. Auch wenn (oder gerade weil) es etwas abgeschweift ist (oder so scheint), sollten wir das zu einem brauchbaren Ende bringen.

Davon ab hätte ich mich ohne die Ausführungen anhand deiner, naja, etwas abstrakt formulierten Problemstellung nicht in das hineinversetzen können, was du vorhast.
Jan.O
User
Beiträge: 61
Registriert: Samstag 26. April 2008, 00:32

Das "ja" bezog sich auf den 2. Teil: Die verbindung kann "unendlich" lange aufrecht erhalten werden.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

[strong]X[/strong]HTML streamen ist eine schlechte Idee weil ältere Browser XHTML Dokumente nur dann rendern können, wenn sie die komplett geladen haben. Zb Firefox 2.
TUFKAB – the user formerly known as blackbird
Antworten