Andreas: Prüfen, ob die Verbindung mit dem Client noch besteht

Hallo,

ich möchte einen kleinen Intranet-Chat in Perl entwickeln. Der HTML-Teil besteht aus einem Frameset: Im oberen Frame der Text, im mittleren Frame ein Texteingabeformular, welches im unteren Frame zum Server geschickt wird.

IDEE:
Damit das obere Chatframe immer aktuell bleibt, gibt es die Möglichkeit mit den HTML- oder JavaScript-Reload-Methoden - allerdings bin ich auf die Idee gekommen das Ganze etwas eleganter zu lösen:

Wenn das obere Chatframe ein Perl Script aufruft, welches die Verbindung zum Client durch ein exit gar nicht erst beendet, weiss ich immer, ob der Benutzer noch im Chat ist und kann außerdem ständig neue Beiträge zum Fenster senden.

PROBLEM:
Das funktioniert soweit auch ganz gut, nur leider kann ich nicht feststellen, ob der Client das Browserfenster geschlossen hat - somit läuft der Perl-Prozess für diesen Benutzer ewig auf dem Server und verbraucht somit nach und nach die Rechnerressourcen. (Und ob der Chatter noch aktiv ist, bekomme ich somit auch nicht mit.)

FRAGE:
Wie kann ich mit Perl feststellen, ob die Verbindung zum Browser des Clients noch besteht?

Ich kann mir nicht vorstellen, dass es dafür keine Lösung gibt, kann aber einfach keine finden. Ich dachte zuerst an eine Anderung in den %ENV-Variablen, aber die werden nur beim Start des Scripts gesetzt und ändern sich nicht mehr. Weiss jemand eine Lösung?

Ciao
Andreas

  1. Hallo Andreas!

    So ohne weiteres wird das nicht funktionieren, denn HTTP- ist ein zustandsloseses Protokoll.
    Nach dem Ausliefern des Dokumentes an den Client (Browser) beendet der Webserver die zuvor geöffnete
    TCP-Verbindung wieder.

    Mit anderen Worten: du kannst nicht feststellen, _ob_ die Verbindung noch besteht - weil sie _nicht mehr_
    besteht, wenn der Browser das HTML-Dokument anzeigt.

    Gruss

    Sven

    1. Hi Sven,

      die Verbindung wird ja von meiner Seite gar nicht beendet. Mein Script befindet sich viel mehr in einem Wartezustand und prüft immer, ob neue Nachrichten von Chattern eingegangen sind. Ist das der Fall, werden die neuen Nachrichten zum Browser gesendet und weitergewartet.

      Sobald ich das Script mit "exit();" beende, wird die HTTP-Verbindung beendet, das ist richtig. Nun will ich aber während des Wartezustands meines Scripts in einem Intervall von 1 Sekunde prüfen, ob die Verbindung nicht von meiner Seite, sondern von der Clientseite getrennt wurde.

      Trennt der Client nämlich die Verbindung - sprich macht der Chatter den Browser zu - wird mein Script leider nicht beendet, sondern wartet und sendet fleißg ohne jede Fehlermeldung weiter.

      Ciao
      Andreas

      1. Hallo!

        die Verbindung wird ja von meiner Seite gar nicht beendet.

        Doch! Wenn der http-Server ein Dokument an den Client gesendet hat
        wird die Verbindung gekappt - von deinem Server!

        Es besteht _keine_ Verbindung zwischen Webserver und Browser, nachdem
        das Dokument komplett ausgeliefert wurde - http arbeitet so: es ist
        zustandslos.

        Probiere mal eine Telnet -Verbindung auf Port 80 und hole dann
        ein Dokument ab - und schaue was passiert:

        Beispiel:
        telnet selfhtml.teamone.de 80
        GET [Enter]

        Gruss Sven

        1. Hi,

          tut mir leid, aber ich muss Dir wiedersprechen... Probier' mal dieses Perl Script aus:

          <CUT>

          #!/usr/bin/perl

          $|=1;# Datenbuffer abschalten - wichtig, sonst werden die Daten erst am Ende des Scripts gesendet

          print "Content-type: text/html\n\n";

          for(my $i=0;$i<=200;$i++){

          sleep(1):
            print "$i<br>";

          }

          exit();

          <CUT>

          Wenn Du dieses Script über einen Browser aufrufst, wird jede Sekunde eine Zahl ausgegeben. Solange, bis exit() aufgerufen wird - aber bis dahin bleibt die Verbindung aktiv. Woher soll denn der Browser wissen, wann das Sokument vollständig geladen ist?: Indem ich das Script durch exit() beende und der Apache Server die HTTP-Verbindung trennt, weil er erkennt, dass das angeforderte Dokument (das Script) den Datenstream beendet hat.

          Wenn Du den Browser allerdings zumachst, während das Script läuft, rennt der Prozess noch solange im Speicher des Servers, bis exit() erreicht ist. Das ist eine Tatsache - Du kannst es mit diesem Testscript selbst nachvollziehen. Als Testumgebung verwende ich Win XP Pro mit Apache und ActivePerl - aber auf einem SuSe Linux Rechner mit Apache und Perl kannst Du es genau so nachvollziehen.

          Ciao
          Andreas

          1. Hallo!

            tut mir leid, aber ich muss Dir wiedersprechen... Probier' mal dieses Perl Script aus:

            Nein, Sven hat Recht. Dein Script macht nichts anderes als den Response des Servers künstlich in die Länge zu ziehen. Das wird immer nach einigen Minuten an irgedeinem timeout scheitern. Der Client schickt ein Request, und der Server sekundenweise den Response, wenn dieser beendet ist wird die Verbindung beendet, oder schon vorher durch einen der vielen serverseitigen oder clientseitigen timeouts. Du kannst innerhalb des Response nichts anderes machen als Daten ausgeben. Du kannst nicht prüfen ob diese Verbindung noch besteht.

            Was Du da machst wird nicht funktionieren, da HTTP für sowas nicht das geeignete Protokoll ist.

            Grüße
            Andreas

            1. Moin Moin !

              Was Du da machst wird nicht funktionieren, da HTTP für sowas nicht das geeignete Protokoll ist.

              In den meisten Fällen nicht. Siehe z.B. SelfChat, dort wird ein Java-Applet benutzt, das "irgendwie anders" zum Chat-Server kommt. Auch mit einer Telnet-Verbindung ist ein Chat gut und einfach zu realisieren.

              Aber mit Server-Push (siehe mein anderes Posting) kann es auch funktionieren.

              Alexander

              --
              Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
              1. Hallo zusammen,

                vielen Dank für Euere Hilfen!

                Es _gibt_ die Möglichkeit die Verbindung zum Client zu überwachen - und zwar mit Apache->request->connection->aborted() [CPAN]. Allerdings wird mir das auch nicht über einen Timeout hinweghelfen.

                Naja, also ich geb's auf mit der permanenten Verbindung, vielleicht fällt mir nochwas Anderes ein.

                Ciao
                Andreas

                1. Hi!

                  Naja, also ich geb's auf mit der permanenten Verbindung, vielleicht fällt mir nochwas Anderes ein.

                  Was ist mit Java? Damit funktioniert es !

                  Gruss Sven

                  1. Hi Sven,

                    Was ist mit Java? Damit funktioniert es !

                    das ist keine Frage der Programmiersprache, sondern des verwendeten Kommunikationsprotokolls.
                    Das Problem liegt in der Verwendung von HTTP, nicht in der Verwendung von Perl.

                    Viele Grüße
                          Michael

                    --
                    T'Pol: I apologize if I acted inappropriately.
                    V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.
                    1. Hi,

                      Was ist mit Java? Damit funktioniert es !

                      das ist keine Frage der Programmiersprache, sondern des verwendeten Kommunikationsprotokolls.
                      Das Problem liegt in der Verwendung von HTTP, nicht in der Verwendung von Perl.

                      Was er IMHO meinte, ist: Er soll einen anderen Client, eventuell in Java geschrieben, benutzten, weil HTTP dafür ja ungeignet ist, und die allermeisten Browser nicht sonderlich viele andere Protokolle mitbringen. Dabei ist die Serverseitige IMHO Sprache egal, kann also Perl sein. ;-)

                      mfg Andres Freund

                      1. Hi!

                        Das Problem liegt in der Verwendung von HTTP, nicht in der Verwendung von Perl.
                        Was er IMHO meinte, ist: Er soll einen anderen Client, eventuell in Java geschrieben, benutzten, weil HTTP dafür ja ungeignet ist, und die allermeisten Browser nicht sonderlich viele andere Protokolle mitbringen. Dabei ist die Serverseitige IMHO Sprache egal, kann also Perl sein. ;-)

                        genau, und java-applets lassen sich ja schön in eine Internetseite einbetten. Slebiges gilf übrigens für flash, da geht das mit XML-sockets, weiß aber noch nicht genau was das ist und ob auch nicht welches Protokoll.

                        Grüße
                        Andreas

                      2. Hallo zusammen,

                        Was er IMHO meinte, ist: Er soll einen anderen Client, eventuell in Java geschrieben, benutzten, weil HTTP dafür ja ungeignet ist,

                        Ja genau das meinte ich - gestern war es schon etwas spät...
                        Natürlich kann man hierzu auch Perl benutzen, aber die Einbindung in eine HTML-Seite ist dann noch nicht gegeben..
                        Deshalb hatte ich die Nutzung eines Java-Applets vorgeschlagen, weil man dieses in eine HTML-Seite einbetten kann. Java kann dann auf andere Protokolle als http zurückgreifen - den folgenden Link  wollte ich gestern noch hinzufügen:

                        http://java.seite.net/chat/index.html

                        Gruss Sven

          2. Moin Moin !

            Andreas hat recht, aber die Implementierung ist nicht sehr sauber.

            Lest mal *beide* den Abschnitt "Server-Push" von http://www.netscape.com/assist/net_sites/pushpull.html.

            Und etwas googlen nach "Content-type: multipart/mixed" schadet sicher auch nicht.

            Alexander

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
          3. Hallo Andreas!

            Jetzt (nach dem Lesen des Quelltextes) verstehe ich was du meinst - stimmt so wird die Verbindung aufrecht
            gehalt, weil du in einer Schleife das Dokument schreibst...es kann und wird aber
            passieren, dass die Verbindung - ungewollt abgebrochen wird.

            Http ist nicht gerade für einen Chat oder andere Formen von Streams geeignet.

            Sven

          4. Hi Andreas,

            for(my $i=0;$i<=200;$i++){
              sleep(1):
              print "$i<br>";
            }

            Wenn Du dieses Script über einen Browser aufrufst, wird jede Sekunde eine Zahl ausgegeben.

            Hast Du mal versucht, das auf einem Apache mit mod_gzip laufen zu lassen? Du wirst Dein blaues Wunder erleben ...

            Viele Grüße
                  Michael

            --
            T'Pol: I apologize if I acted inappropriately.
            V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.