Marcel Czerny: HTTP-Request abbrechen

Hallo Leute,

Ich habe jetzt einige Zeit im Internet danach recherchiert, aber keiner traut sich eine solche Frage zu stellen ;-)

Ist es prinzipiell möglich eine ausgelöste Web-Anforderung vor Erhalt der Antwort zu stornieren?

Also, der User löst durch einen Klick (o.ä.) in seinem Browser einen HTTP-Request auf dem Server aus,
der startet daraufhin einen evtl. aufwendigen CGI-Prozess.
Jetzt klickt der User irgendwo anders hin, braucht das Ergebnis also gar nicht.
Könnte man mittels Javascript den alten Request canceln und damit den Server entlasten?

Gibt das HTTP-Protokoll so etwas her?

Und wenn es nicht geht, kann man das irgenwo nachlesen?

Vielen Dank schon mal
Marcel

  1. Hallo,

    Ich habe jetzt einige Zeit im Internet danach recherchiert, aber keiner traut sich eine solche Frage zu stellen ;-)

    Ist es prinzipiell möglich eine ausgelöste Web-Anforderung vor Erhalt der Antwort zu stornieren?

    Also, der User löst durch einen Klick (o.ä.) in seinem Browser einen HTTP-Request auf dem Server aus,
    der startet daraufhin einen evtl. aufwendigen CGI-Prozess.
    Jetzt klickt der User irgendwo anders hin, braucht das Ergebnis also gar nicht.
    Könnte man mittels Javascript den alten Request canceln und damit den Server entlasten?

    Auch mit einer einfachen Anfrag nach HTTP, also einem simplem Link.

    Das Problem liegt auf dem Server. Der CGI Prozess muß am User hängen (Session ID o.ä.), sodaß beim Klicken auf einen anderen Link (Da sollte es nicht viele andere geben, sonst wird's unübersichtlich und vor allem keine nach "draussen")
    nur noch dafür Sorge getragen werden muß, daß der passende CGI Prozess gekillt wird.

    Bringt natürlich nichts, wenn ganz abgebrochen, sprich: das Browserfenster geschlossen oder eine andere Adresse angesurft wird.

    Aber wenn der CGI Prozess wirklich sehr aufwendig ist (Volltextsuche über eine riesige Datenbank o.ä.) sollte sich oben beschriebener Aufwand schon lohnen.

    Zumindest läßt sich so ein "Abbrechen" Button leicht einbauen.
    Ob der dann benutzt wird, ist natürlich wieder eine andere Frage ;-)

    Gibt das HTTP-Protokoll so etwas her?

    Direkt nicht.

    so short

    Christoph Zurnieden

    1. Hallo,

      Das Problem liegt auf dem Server. Der CGI Prozess muß am User hängen (Session ID o.ä.), sodaß beim Klicken auf einen anderen Link (Da sollte es nicht viele andere geben, sonst wird's unübersichtlich und vor allem keine nach "draussen")
      nur noch dafür Sorge getragen werden muß, daß der passende CGI Prozess gekillt wird.

      Ich denke so werde ich es machen (müssen).

      Ich danke Euch auch für die interessante Diskusion.
      Auch ohne Lösung lernt man doch schon durch die genaue Durchleuchtung des Problems einiges dazu ;-)

      Grüße
      Marcel

  2. Ist es prinzipiell möglich eine ausgelöste Web-Anforderung vor Erhalt der Antwort zu stornieren?

    Ja.

    Also, der User löst durch einen Klick (o.ä.) in seinem Browser einen HTTP-Request auf dem Server aus,
    der startet daraufhin einen evtl. aufwendigen CGI-Prozess.
    Jetzt klickt der User irgendwo anders hin, braucht das Ergebnis also gar nicht.
    Könnte man mittels Javascript den alten Request canceln und damit den Server entlasten?

    Viel zu aufwendig. Eine TCP-Verbindung lässt sich ohne weiteres mittendrin abbrechen und der Eigentümer (hier: der Webserver) der Verbindung wird darüber automatisch informiert.
    Du musst nur dafür sorgen, daß Dein Skript auf dieses Ereignis reagiert. PHP bricht beispielsweise (zumindest in der Modulversion) ein Skript standardmäßig ab, sobald es versucht, in eine bereits geschlossene Verbindung zu schreiben (lässt sich aber ändern, http://www.php.net/manual/de/features.connection-handling.php). mod_fastcgi macht's ähnlich und signalisiert dem Prozess das Verbindungsende (http://www.fastcgi.com/docs/faq.html#Signals).

    Unter Umständen etwas hinderlich könnten allerdings Caches sein, die dafür sorgen, daß die Anfrage komplett ausgeführt wird, egal ob der Browser die Verbindung beendet hat oder nicht.
    Das hat aber durchaus seinen Sinn und Zweck und mit passender Nutzung von Expires oder Last-Modified bzw. If-Modified-Since kann man dank der Cache-Zwischenspeicherung eventuell auch die ein oder andere Abfrage zumindest mit der Meldung "Keine Änderung seit letztem Abruf" frühzeitig beenden oder sogar ganz verhindern.

    Gruß,
      soenk.e

    1. Hallo,

      Also, der User löst durch einen Klick (o.ä.) in seinem Browser einen HTTP-Request auf dem Server aus,
      der startet daraufhin einen evtl. aufwendigen CGI-Prozess.
      Jetzt klickt der User irgendwo anders hin, braucht das Ergebnis also gar nicht.
      Könnte man mittels Javascript den alten Request canceln und damit den Server entlasten?

      Viel zu aufwendig. Eine TCP-Verbindung lässt sich ohne weiteres mittendrin abbrechen und der Eigentümer (hier: der Webserver) der Verbindung wird darüber automatisch informiert.

      Da würde ich jetzt aber gerne wissen, wie Du die Ausführung des TCP unterbrechen willst und zwar ohne Eingriffe in's OS oder den Stecker raus zu ziehen.
      Nur mit dem Browser?

      Du musst nur dafür sorgen, daß Dein Skript auf dieses Ereignis reagiert. PHP bricht beispielsweise (zumindest in der Modulversion) ein Skript standardmäßig ab, sobald es versucht, in eine bereits geschlossene Verbindung zu schreiben (lässt sich aber ändern, http://www.php.net/manual/de/features.connection-handling.php). mod_fastcgi macht's ähnlich und signalisiert dem Prozess das Verbindungsende (http://www.fastcgi.com/docs/faq.html#Signals).

      Aha.
      Nun ist aber nach dem Absenden des Requests schon Ende.
      Bei einem unvollständigem (Timeout) oder abgebrochenem Request startet das CGI o.ä. gar nicht erst.
      Genau so beim Response: Wenn ein Response vorliegt, ist das CGI meist schon fertig. Gäbe ja sonst auch kein Ergebnis, das raus zu schicken wäre.
      Die einzige Ausnahme wäre ein Stream, das läuft aber bei Audio/Video nicht unbedingt über das HTT Protokol und da ist ein Abbruch auch direkt vorgesehen und fest eingebaut.

      Unter Umständen etwas hinderlich könnten allerdings Caches sein, die dafür sorgen, daß die Anfrage komplett ausgeführt wird, egal ob der Browser die Verbindung beendet hat oder nicht.

      Was hat das mit Caches zu tun?
      Bei meinem Beispiel mit der Volltextsuche wird diese angeschmissen und läuft getrennt vom HTTP. Die müßte man explizit anweisen aufzuhören. Das geht mit verschiedenen Methoden, die teilweise allerdings auch die Browser unterstützen müssen.

      RFC 2616:
        HTTP implementations SHOULD implement persistent connections.
      _______________________^^^^^^

      Tja ...

      Das hat aber durchaus seinen Sinn und Zweck und mit passender Nutzung von Expires oder Last-Modified bzw. If-Modified-Since kann man dank der Cache-Zwischenspeicherung eventuell auch die ein oder andere Abfrage zumindest mit der Meldung "Keine Änderung seit letztem Abruf" frühzeitig beenden oder sogar ganz verhindern.

      Das ist eine empfehlenswerte zusätzliche Sicherungsmaßnahme, die aber auch nicht immer paßt. Mitunter gibt es nichts zu cachen.

      so short

      Christoph Zurnieden

      1. Hallo Christoph,

        daß man für HTTP-Request und Response _jeweils_ eine Verbindung braucht, würde mich wundern, da z.B. mein Paketfilter alle eingehenden Verbindungen blockiert.
        Somit könnte ich ja nichts per HTTP bekommen.
        Ne, HTTP-Request und -Response werden über eine TCP-Verbindung gesendet, da bin ich mir ganz sicher.

        Schönen Gruß aus Bilk

        Rainer

        1. Halihallo Rainer

          daß man für HTTP-Request und Response _jeweils_ eine Verbindung braucht, würde mich wundern, da z.B. mein Paketfilter alle eingehenden Verbindungen blockiert.
          Somit könnte ich ja nichts per HTTP bekommen.
          Ne, HTTP-Request und -Response werden über eine TCP-Verbindung gesendet, da bin ich mir ganz sicher.

          Wo hat Christoph das denn bitteschön behauptet? - Ich sehe keine derartige Aussage. Aber du hast natürlich recht, Request und Response laufen über eine einzige Socketverbindung.

          Viele Grüsse

          Philipp

          1. Hi,

            das hier:

            Aha.
            Nun ist aber nach dem Absenden des Requests schon Ende.
            Bei einem unvollständigem (Timeout) oder abgebrochenem Request startet das CGI o.ä. gar nicht erst.
            Genau so beim Response: Wenn ein Response vorliegt, ist das CGI meist schon fertig. Gäbe ja sonst auch kein Ergebnis, das raus zu schicken wäre.

            habe ich wohl irrtümlicherweise auf die TCP-Verbindung bezogen.
            Wenn ichs's jetzt nochmal im Zusammenhang lese, wird es klarer...

            Schönen Gruß

            Rainer
            ...der jetzt eine Reise in die Zeit vor HTTP macht ;-)

            1. Halihallo Rainer

              Nun ist aber nach dem Absenden des Requests schon Ende.
              Bei einem unvollständigem (Timeout) oder abgebrochenem Request startet das CGI o.ä. gar nicht erst.
              Genau so beim Response: Wenn ein Response vorliegt, ist das CGI meist schon fertig. Gäbe ja sonst auch kein Ergebnis, das raus zu schicken wäre.

              habe ich wohl irrtümlicherweise auf die TCP-Verbindung bezogen.
              Wenn ichs's jetzt nochmal im Zusammenhang lese, wird es klarer...

              Okidoki, hab's mir gedacht :-)

              ...der jetzt eine Reise in die Zeit vor HTTP macht ;-)

              http://forum.de.selfhtml.org/archiv/2002/7/18616/#m104637

              vielleicht kann ich dir die Reise verkürzen :-)

              Viele Grüsse

              Philipp

      2. Viel zu aufwendig. Eine TCP-Verbindung lässt sich ohne weiteres mittendrin abbrechen und der Eigentümer (hier: der Webserver) der Verbindung wird darüber automatisch informiert.

        Da würde ich jetzt aber gerne wissen, wie Du die Ausführung des TCP unterbrechen willst und zwar ohne Eingriffe in's OS oder den Stecker raus zu ziehen.

        Indem man die Verbindung schließt, ganz einfach, zum Beispiel mit close() oder socket_close() oder was das System gerade dazu zur Verfügung stellt bzw. wie man die Verbindung aufgebaut hat (Dateisystem, Netzwerkebene).

        Du musst nur dafür sorgen, daß Dein Skript auf dieses Ereignis reagiert.

        Nun ist aber nach dem Absenden des Requests schon Ende.

        Na, wo kriegt der Browser denn dann die Antwort her, wenn er nach dem Absenden der HTTP-Anfrage gleich die Verbindung kappt? Wie ungeduldig ;)

        Genau so beim Response: Wenn ein Response vorliegt, ist das CGI meist schon fertig. Gäbe ja sonst auch kein Ergebnis, das raus zu schicken wäre.

        Könntest Du Dich bitte auf Deutsch ausdrücken? Was meinst Du mit "wenn ein Response vorliegt"?

        Falls Du Ausgaben meinst: Es hängt doch wohl vom Skript/Programm ab, wann es etwas ausgibt. Warum sollte es beispielsweise nicht als erstes den Seitenkopf ausgeben, dann seine Berechnungen durchführen, während dieser Berechnungen schon Teilergebnisse ausgeben und am Ende nochmal den Seitenfuß hinterherschicken. Dann wird während der gesamten Laufzeit des Skriptes etwas ausgegeben.

        Insofern verstehe ich nicht, warum "das CGI meist schon fertig" sein soll? Entsprechend obigem Ablauf würde ich glatt das genaue Gegenteil behaupten. Skripte geben eher nur in Ausnahmefällen einzig kurz vorm Beenden etwas aus. Da müsste man ja umständlicherweise sämtliche Ausgaben zwischendurch sammeln - diese Mühe werden sich meiner Einschätzung nach eher die wenigsten machen (sofern nicht schon eine Puffer-Automatik eingebaut ist).

        Die einzige Ausnahme wäre ein Stream, das läuft aber bei Audio/Video nicht unbedingt über das HTT Protokol und da ist ein Abbruch auch direkt vorgesehen und fest eingebaut.

        Äh, ich glaube, Du solltest Dich mal mit den Grundlagen von HTTP einerseits und TCP andererseits beschäftigen. HTTP hat mit der darunterliegenden Netzwerkverbindung TCP absolut garnichts zu tun. HTTP sieht keinen "Befehl" zum unerwarteten Beenden einer Verbindung vor, das stimmt. Das ist auch nicht nötig, weil man einfach die Netzwerkverbindung (TCP) beendet.

        Ein HTTP-Client baut eine Verbindung zum HTTP-Server auf, diese Verbindung verwendet in der Regel das TCP-Protokoll - wie ein Großteil aller anderen Internetverbindungen auch. Steht diese Verbindung, schicken sich die beiden Programme gegenseitig Daten, und zwar entsprechend dem HTTP-Protokoll.
        Diese TCP-Verbindung steht (sofern sie nicht abgebrochen wird) während des gesamten Austauschs von Anfrage und Antwort und, bei keep-alive-HTTP-Verbindungen, auch noch für weitere Anfrage/Antwort-Pärchen, ähnlich einem Telefongespräch.

        TCP kannst Du Dir als das Telefonnetz vorstellen, daß Deine Töne (Worte) transportiert, HTTP definiert die Sprache, also die Worte, die Du benutzt: Deutsch, Englisch, Suaheli.
        Du stellst also erst die Verbindung her, indem Du den Telefonhörer abhebst und wählst, und wenn die Verbindung steht (bis hier hin TCP), kommunizierst Du mit der "Gegenstelle" (HTTP). Die "HTTP-Verbindung" kannst Du zu jeder beliebigen Zeit abbrechen, indem Du den Telefonhörer auflegst. Und Deine Gegenstelle bekommt das dann entsprechend signalisiert - ist sie klug, reagiert sie darauf, wenn nicht, sabbelt sie solange weiter, bis sie merkt, daß keine Antwort mehr kommt (Neudeutsch: Timeout).

        Wie man eine TCP-Verbindung in der Praxis aufbaut und dann für HTTP verwendet, kannst Du Dir unter http://www.php.net/manual/de/ref.sockets.php, Beispiel 2, anschauen. Das ist zwar PHP (hab auf die schnelle nichts schöneres gefunden), tut aber nichts zur Sache, denn das Prinzip ist immer dasselbe (weil alle auf demselben Software-Urahn aufbauen).

        Unter Umständen etwas hinderlich könnten allerdings Caches sein, die dafür sorgen, daß die Anfrage komplett ausgeführt wird, egal ob der Browser die Verbindung beendet hat oder nicht.

        Was hat das mit Caches zu tun?

        Wenn der Anzeigeteil eines Browsers ein Dokument abfragt, aber vorzeitig abricht, bedeutet das noch lange nicht, daß ein zwischen Anzeigeteil und Server sitzender Cache, egal welcher Art, die Verbindung zum Server ebenfalls abbricht.
        Der Cache könnte sich ja genauso gut denken "Na, die Anfrage wurde zwar abgebrochen, aber wenn sie nochmal kommt, hab ich die Antwort schon hier" und lässt den Server trotzdem weiterarbeiten.

        Gruß,
          soenk.e

        1. Nun gut,
          aber wie geht das nun praktisch?
          Was muß ich in Javascript tun um dem Server den Abbruch zu signalisieren.
          Ein Klick auf den Stop-Knopf des Browsers verhindert zwar das der Browser die Seite weiter lädt (bzw. der Befehl "stop()" für NS), aber auf dem Server arbeitet das CGI-Script trotzdem weiter - wird also vom Web-Server nicht automatisch "gekillt".
          Kann ich im Script den Abbruch-Wunsch des Browsers irgendwie abfragen und mich dann selbst beenden?

          Gruß
          Marcel

          1. Nun gut,
            aber wie geht das nun praktisch?
            Was muß ich in Javascript tun um dem Server den Abbruch zu signalisieren.
            Ein Klick auf den Stop-Knopf des Browsers verhindert zwar das der Browser die Seite weiter lädt (bzw. der Befehl "stop()" für NS), aber auf dem Server arbeitet das CGI-Script trotzdem weiter - wird also vom Web-Server nicht automatisch "gekillt".
            Kann ich im Script den Abbruch-Wunsch des Browsers irgendwie abfragen und mich dann selbst beenden?

            Entschuldigung - die CGI-Scripte sind in Perl
            ...hatte ich vergessen zu erwähnen.

            Gruß
            Marcel

          2. aber wie geht das nun praktisch?
            Was muß ich in Javascript tun um dem Server den Abbruch zu signalisieren.

            Garnichts. Sobald der Anwender Stopp drückt oder eine andere Seite auswählt, bricht der Browser die Verbindung in der Regel selbsttätig ab.

            Ein Klick auf den Stop-Knopf des Browsers verhindert zwar das der Browser die Seite weiter lädt (bzw. der Befehl "stop()" für NS), aber auf dem Server arbeitet das CGI-Script trotzdem weiter - wird also vom Web-Server nicht automatisch "gekillt".

            Nein, wie ich bereits sagte, muß Dein Skript (auf Serverseite) auf diesen Verbindungsabbruch reagieren, es wird _nicht_ einfach vom Server über die Klippen gestoßen.

            Kann ich im Script den Abbruch-Wunsch des Browsers irgendwie abfragen und mich dann selbst beenden?

            Wenn Dein Server Dir dieses Ereignis mitteilt, ja. Ob das beim Apache im normalen CGI-Modul der Fall ist, weiß ich nicht, daß müsstest Du ausprobieren (siehe unten). Steckt das FastCGI-Modul im Server, wird der Verbindungsabbruch signalisiert.

            In der FAQ zu FastCGI, auf die ich bereits hingewiesen hatte (http://www.fastcgi.com/docs/faq.html#Signals), heißt es dazu:

            "[Das Signal] PIPE occurs when trying to write/print to a file
               descriptor that has been closed."

            Mit "file descriptor" ist die Standardausgabe gemeint, die bei CGI-Anwendungen in Richtung Apache zeigt. Wird die Verbindung Client<->Apache abgebrochen, wird auch die Standardausgabe (also CGI->Apache) durch den Server geschlossen.

            Weiterhin:

            "Ideally, [PIPE] should result in an early abort of the request
               handling within your application and a return to the top of the
               FastCGI accept() loop."

            Dort ist auch beschrieben, wie man in Perl auf Signale reagiert.

            Du solltest also erstmal schauen, ob FastCGI in Deinem Webserver steckt, und wenn nicht, den Serverbetreiber bitten, dieses Modul einzufügen.
            Du kannst natürlich auch mal probieren, ob Du dieses Signal auch unter "normalen" CGI-Umständen erhälst.

            Gruß,
              soenk.e

        2. Hallo,

          Viel zu aufwendig. Eine TCP-Verbindung lässt sich ohne weiteres mittendrin abbrechen und der Eigentümer (hier: der Webserver) der Verbindung wird darüber automatisch informiert.

          Da würde ich jetzt aber gerne wissen, wie Du die Ausführung des TCP unterbrechen willst und zwar ohne Eingriffe in's OS oder den Stecker raus zu ziehen.

          Indem man die Verbindung schließt, ganz einfach, zum Beispiel mit close() oder socket_close() oder was das System gerade dazu zur Verfügung stellt bzw. wie man die Verbindung aufgebaut hat (Dateisystem, Netzwerkebene).

          Das ist "den Stecker rausziehen" ;-)

          Aber es geht hier um die Clientseite. Da gibt es zuviele Clients als das man sich Serverseitig auf irgendetwas verlassen könnte.

          Du musst nur dafür sorgen, daß Dein Skript auf dieses Ereignis reagiert.

          Nun ist aber nach dem Absenden des Requests schon Ende.

          Na, wo kriegt der Browser denn dann die Antwort her, wenn er nach dem Absenden der HTTP-Anfrage gleich die Verbindung kappt? Wie ungeduldig ;)

          Doch, es ist dann Ende. Er kann nur die (fehlende) Response ignorieren und einen weiteren Request schicken.
          Es ist auch nicht möglich ohne Nachfrage festzustellen, ob die Verbindung gekappt wurde, oder nur dauert. Da könnte dann nur ein brutales Timeout greifen. Siehe auch RFC 1122 u.N.

          Genau so beim Response: Wenn ein Response vorliegt, ist das CGI meist schon fertig. Gäbe ja sonst auch kein Ergebnis, das raus zu schicken wäre.

          Könntest Du Dich bitte auf Deutsch ausdrücken? Was meinst Du mit "wenn ein Response vorliegt"?

          Falls Du Ausgaben meinst: Es hängt doch wohl vom Skript/Programm ab, wann es etwas ausgibt. Warum sollte es beispielsweise nicht als erstes den Seitenkopf ausgeben, dann seine Berechnungen durchführen, während dieser Berechnungen schon Teilergebnisse ausgeben und am Ende nochmal den Seitenfuß hinterherschicken. Dann wird während der gesamten Laufzeit des Skriptes etwas ausgegeben.

          Ja, so funktioniert die Mehrzahl der Scripte.
          Allerdings wird auch selten während der _ganzen_ Laufzeit der Scripte etwas ausgegeben.

          Insofern verstehe ich nicht, warum "das CGI meist schon fertig" sein soll? Entsprechend obigem Ablauf würde ich glatt das genaue Gegenteil behaupten. Skripte geben eher nur in Ausnahmefällen einzig kurz vorm Beenden etwas aus. Da müsste man ja umständlicherweise sämtliche Ausgaben zwischendurch sammeln - diese Mühe werden sich meiner Einschätzung nach eher die wenigsten machen (sofern nicht schon eine Puffer-Automatik eingebaut ist).

          Ja, es scheint, das ich hier zu sehr verallgemeinert habe.

          Allerdings würde ich es nicht so bauen. Ich würde erst abwarten, ob das Script fehlerlos durchläuft, bevor ich anfange zu senden.
          Insbesondere beim Forken von großen Datenbankabfragen ist das von Vorteil, da so ein Hauptteil der Fehler vorweg abgefangen werden können, da muß dann keiner warten, bis irgendwo ein Timeout greift.
          Oder wie bei gzip, ob die Kompression jetzt funktioniert hat oder plain gesendet wird. Beides erfordert schließlich andere Header.

          Nötigt natürlich zur sauberen Programmierung ;-)

          Die einzige Ausnahme wäre ein Stream, das läuft aber bei Audio/Video nicht unbedingt über das HTT Protokol und da ist ein Abbruch auch direkt vorgesehen und fest eingebaut.

          Äh, ich glaube, Du solltest Dich mal mit den Grundlagen von HTTP einerseits und TCP andererseits beschäftigen.

          Noch näher?

          Hey, ich habe tcp*.c schon nackich gesehen!
          Pfui Deibel, nicht noch näher! ;-)

          (Sorry, Allan, but you know what I mean, don't you? ;-)

          HTTP hat mit der darunterliegenden Netzwerkverbindung TCP absolut garnichts zu tun. HTTP sieht keinen "Befehl" zum unerwarteten Beenden einer Verbindung vor, das stimmt. Das ist auch nicht nötig, weil man einfach die Netzwerkverbindung (TCP) beendet.

          Und wie machst Du das sauber(!) mit einem Browser?

          Ein HTTP-Client baut eine Verbindung zum HTTP-Server auf, diese Verbindung verwendet in der Regel das TCP-Protokoll - wie ein Großteil aller anderen Internetverbindungen auch.

          Bemerkung des paranoiden Sicherheitsfanatikers: "Schlimm genug!"

          Steht diese Verbindung, schicken sich die beiden Programme gegenseitig Daten, und zwar entsprechend dem HTTP-Protokoll.

          Bemerkung eines bekannten Webserverprogammierers:"Schön wär's!"

          Diese TCP-Verbindung steht (sofern sie nicht abgebrochen wird) während des gesamten Austauschs von Anfrage und Antwort und, bei keep-alive-HTTP-Verbindungen, auch noch für weitere Anfrage/Antwort-Pärchen, ähnlich einem Telefongespräch.

          Bitte mit einem mehr oder minder kurzem Zitat aus RFC 2616 belegen, danke.
          (Tip: steht ganz oben)
          Und jetzt auch noch aus RFC 1122
          Aha, dacht' ich mir ;-)

          Ich hoffe Du kannst jetzt nachvollziehen, warum sich manch' Programmierer, der sowas implementieren soll, ernsthaft fragt, welcher hirnverbrannte Idiot sich Derartiges ausdenkt.

          "Ein gewachsenes System", nun:"Gewuchert" träfe es eher.

          TCP kannst Du Dir als das Telefonnetz vorstellen, daß Deine Töne (Worte) transportiert, HTTP definiert die Sprache, also die Worte, die Du benutzt: Deutsch, Englisch, Suaheli.

          Schöner Vergleich. Hinkt zwar arg, aber tät er das nicht, wär's kein Vergleich, oder? ;-)

          Nein, ernsthaft, gutes Bild, sollte man sich merken.

          Du stellst also erst die Verbindung her, indem Du den Telefonhörer abhebst und wählst, und wenn die Verbindung steht (bis hier hin TCP), kommunizierst Du mit der "Gegenstelle" (HTTP). Die "HTTP-Verbindung" kannst Du zu jeder beliebigen Zeit abbrechen, indem Du den Telefonhörer auflegst.

          Aha, hier hakt das Bild. Nach HTTP würdest Du einfach mit dem Sprechen aufhören. Ob Du auflegst interessiert HTTP nicht mehr. Das muß der Browser (Im HTTP heißt er ganz allgemein "User Agent", kann ja auch LWP::Simple sein, o.ä.) bzw der Server dann erledigen.

          Und Deine Gegenstelle bekommt das dann entsprechend signalisiert - ist sie klug, reagiert sie darauf, wenn nicht, sabbelt sie solange weiter, bis sie merkt, daß keine Antwort mehr kommt (Neudeutsch: Timeout).

          Wie man eine TCP-Verbindung in der Praxis aufbaut und dann für HTTP verwendet, kannst Du Dir unter http://www.php.net/manual/de/ref.sockets.php, Beispiel 2, anschauen. Das ist zwar PHP (hab auf die schnelle nichts schöneres gefunden), tut aber nichts zur Sache, denn das Prinzip ist immer dasselbe (weil alle auf demselben Software-Urahn aufbauen).

          Kann PHP nicht gut genug, bin da eher C-Programmierer und würde dafür in den Kernel schauen.
          Aber nur unter Zwang! ;-)

          Unter Umständen etwas hinderlich könnten allerdings Caches sein, die dafür sorgen, daß die Anfrage komplett ausgeführt wird, egal ob der Browser die Verbindung beendet hat oder nicht.

          Was hat das mit Caches zu tun?

          Wenn der Anzeigeteil eines Browsers ein Dokument abfragt, aber vorzeitig abricht, bedeutet das noch lange nicht, daß ein zwischen Anzeigeteil und Server sitzender Cache, egal welcher Art, die Verbindung zum Server ebenfalls abbricht.
          Der Cache könnte sich ja genauso gut denken "Na, die Anfrage wurde zwar abgebrochen, aber wenn sie nochmal kommt, hab ich die Antwort schon hier" und lässt den Server trotzdem weiterarbeiten.

          Naja, wenn's dann zu Proxies etc kommt, wird's ganz kniffelig und gefährdet arg die geistige Gesundheit. Sollte man bei solchen Überlegungen sicherheitshalber außen vor lassen. Ist gesünder.

          so short

          Christoph Zurnieden

          1. Viel zu aufwendig. Eine TCP-Verbindung lässt sich ohne weiteres mittendrin abbrechen und der Eigentümer (hier: der Webserver) der Verbindung wird darüber automatisch informiert.

            Da würde ich jetzt aber gerne wissen, wie Du die Ausführung des TCP unterbrechen willst und zwar ohne Eingriffe in's OS oder den Stecker raus zu ziehen.

            Indem man die Verbindung schließt, ganz einfach, zum Beispiel mit close() oder socket_close()

            Aber es geht hier um die Clientseite. Da gibt es zuviele Clients als das man sich Serverseitig auf irgendetwas verlassen könnte.

            Verlassen kann man sich nie auf sowas. Das hatte ich ja versucht, mit dem Hinweis auf möglicherweise zwischengeschaltete Caches zu verdeutlichen.

            IMHO ist das aber kein Grund, aufwendige Javascript/Session/Sonstwas-Abbruchkonstruktionen zu basteln. Denn _sowas_ führt meiner Erfahrung nach nur zu mehr Problemen als das es welche löst. Wie Du bereits sagtest: es gibt "zuviele Clients als das man sich [..] auf irgendetwas verlassen könnte" - da nehme ich doch lieber den einfachsten Weg.

            Du musst nur dafür sorgen, daß Dein Skript auf dieses Ereignis reagiert.

            Nun ist aber nach dem Absenden des Requests schon Ende.

            [..]

            Doch, es ist dann Ende. Er kann nur die (fehlende) Response ignorieren und einen weiteren Request schicken.
            Es ist auch nicht möglich ohne Nachfrage festzustellen, ob die Verbindung gekappt wurde, oder nur dauert.

            Ich kenne mich nicht mit jedem einzelnen TCP-Stack aus, aber soweit mir bekannt, wird eine von der Gegenstelle geschlossene Verbindung dem Prozess vom TCP-Stack signalisiert. So war es zumindest bei der Amiga-Implementation des BSD-Stacks. Hab jetzt keine Lust, die Linux-Dokus durchzuwühlen, aber ich könnte mir vorstellen, daß auch dort eine geschlossene Verbindung signalisiert wird, beispielsweise indem select() oder andere Funktionen einen End-Of-File- oder Broken-Pipe-Fehler liefern (wie es FastCGI beim Verbindungsabbruch macht).

            HTTP hat mit der darunterliegenden Netzwerkverbindung TCP absolut garnichts zu tun. HTTP sieht keinen "Befehl" zum unerwarteten Beenden einer Verbindung vor, das stimmt. Das ist auch nicht nötig, weil man einfach die Netzwerkverbindung (TCP) beendet.

            Und wie machst Du das sauber(!) mit einem Browser?

            Was meinst Du mit sauber? Für mich ist es sauber genug, wenn ich meine TCP-Verbindung mit der dafür vorgesehenen Systemfunktion ordentlich schließe. Fertig.
            So ist es auch in der HTTP-Spezifikation dokumentiert und mit mehr oder weniger unerwartet abbrechenden Verbindungen sollte im übrigen jede Netzwerkapplikation schon von Natur aus rechnen.

            Diese TCP-Verbindung steht (sofern sie nicht abgebrochen wird) während des gesamten Austauschs von Anfrage und Antwort und, bei keep-alive-HTTP-Verbindungen, auch noch für weitere Anfrage/Antwort-Pärchen, ähnlich einem Telefongespräch.

            Bitte mit einem mehr oder minder kurzem Zitat aus RFC 2616 belegen, danke.

            Was soll ich belegen? Sorry, aber ich verstehe im Moment wirklich nicht, was Du meinst. Die Netzwerkverbindung besteht während der gesamten Abwicklung von HTTP-Anfrage/Antwort. Das muß sie auch, denn wie soll der Server bitte die Antwort schicken, wenn der Client die Netzwerkverbindung schließt, nachdem er seine Anfrage geschickt hat? Du behauptest doch wohl nicht etwa, daß der Server dann seinerseits eine eigene Netzwerkverbinung zum Client aufbaut?

            Um's mit dem Telefonbeispiel darzustellen: Deiner Ansicht nach rufst Du also Deine Freundin an, stellst eine Frage, legst auf und dann ruft Deine Freundin Dich an, um Dir zu antworten?! Mit Verlaub, das ist doch Unfug. Und auch ein Gespräch ist doch wohl für Dich nicht beendet, wenn Du Deine letzte Frage gestellt hast, sondern erst dann, wenn Du zur Frage die Antwort bekommen hast (oder der Gesprächspartner das Zimmer verlässt).

            Und jetzt auch noch aus RFC 1122
            Aha, dacht' ich mir ;-)

            Bitte drück dich etwas klarer aus und beschreibe, wie Du das Zusammenspiel von TCP und HTTP zwischen Server und Client siehst, danke. Die "Ich weiß es man besser, aber ich sag's Dir nicht, ätschibätsch"-Schiene finde ich jedenfalls nicht sehr erhellend :/

            Ich hoffe Du kannst jetzt nachvollziehen, warum sich manch'

            Nein, solange Du in Rätseln sprichst, kann ich Deine Sicht der Dinge nicht nachvollziehen.

            Du stellst also erst die Verbindung her, indem Du den Telefonhörer abhebst und wählst, und wenn die Verbindung steht (bis hier hin TCP), kommunizierst Du mit der "Gegenstelle" (HTTP). Die "HTTP-Verbindung" kannst Du zu jeder beliebigen Zeit abbrechen, indem Du den Telefonhörer auflegst.

            Aha, hier hakt das Bild. Nach HTTP würdest Du einfach mit dem Sprechen aufhören. Ob Du auflegst interessiert HTTP nicht mehr. Das muß der Browser (Im HTTP heißt er ganz allgemein "User Agent", kann ja auch LWP::Simple sein, o.ä.) bzw der Server dann erledigen.

            Ja, und? Die Verbindung zwischen Webserver und -client besteht nunmal aus der _Einheit_ TCP und HTTP. HTTP führt übrigens kein Eigenleben, es wird vom Browser angewendet. Insofern kann es sich nicht garicht "für irgendetwas interessieren", der einzige Interessierte ist der Browser, und der sieht sowohl seine HTTP-Anfrage als auch seine Netzwerkverbindung.

            So, und noch zwei der gewünschten Zitate aus RFC 2616, 8.1.4, "Practical Considerations":

            "A client, server, or proxy MAY close the transport connection at
               any time."

            "This means that clients, servers, and proxies MUST be able to
               recover from asynchronous close events."

            Alles andere wäre vom Design her auch ganz großer Mist, dazu sind solche Verbindungen einfach zu unsicher.

            Gruß,
              soenk.e

            1. Hallo,

              IMHO ist das aber kein Grund, aufwendige Javascript/Session/Sonstwas-Abbruchkonstruktionen zu basteln. Denn _sowas_ führt meiner Erfahrung nach nur zu mehr Problemen als das es welche löst. Wie Du bereits sagtest: es gibt "zuviele Clients als das man sich [..] auf irgendetwas verlassen könnte" - da nehme ich doch lieber den einfachsten Weg.

              Ich fand das den einfachsten Weg (den über Sessions)
              Wenn Du etwas Einfacheres hast: nur raus damit!
              Ich wäre der Letzte, der sowas nicht begrüßen würde.

              Du musst nur dafür sorgen, daß Dein Skript auf dieses Ereignis reagiert.

              Nun ist aber nach dem Absenden des Requests schon Ende.
              [..]
              Doch, es ist dann Ende. Er kann nur die (fehlende) Response ignorieren und einen weiteren Request schicken.
              Es ist auch nicht möglich ohne Nachfrage festzustellen, ob die Verbindung gekappt wurde, oder nur dauert.

              Ich kenne mich nicht mit jedem einzelnen TCP-Stack aus, aber soweit mir bekannt, wird eine von der Gegenstelle geschlossene Verbindung dem Prozess vom TCP-Stack signalisiert. So war es zumindest bei der Amiga-Implementation des BSD-Stacks. Hab jetzt keine Lust, die Linux-Dokus durchzuwühlen, aber ich könnte mir vorstellen, daß auch dort eine geschlossene Verbindung signalisiert wird, beispielsweise indem select() oder andere Funktionen einen End-Of-File- oder Broken-Pipe-Fehler liefern (wie es FastCGI beim Verbindungsabbruch macht).

              Ja, ist genauso, da Linux später eigentlich auch nur die BSD Implementation übernommen hat.
              Mit einigen Änderungen, aber das würde hier dann doch zu weit führen ;-)

              Das Problem bei TCP ist nur, das die Verbindung _aktiv_ geschlossen werden muß.
              Ansonsten kann nur ein Timeout greifen.

              HTTP hat mit der darunterliegenden Netzwerkverbindung TCP absolut garnichts zu tun. HTTP sieht keinen "Befehl" zum unerwarteten Beenden einer Verbindung vor, das stimmt. Das ist auch nicht nötig, weil man einfach die Netzwerkverbindung (TCP) beendet.

              Und wie machst Du das sauber(!) mit einem Browser?

              Was meinst Du mit sauber? Für mich ist es sauber genug, wenn ich meine TCP-Verbindung mit der dafür vorgesehenen Systemfunktion ordentlich schließe. Fertig.

              Schön, aber wie machst Du es mit einem Browser?

              So ist es auch in der HTTP-Spezifikation dokumentiert und mit mehr oder weniger unerwartet abbrechenden Verbindungen sollte im übrigen jede Netzwerkapplikation schon von Natur aus rechnen.

              Ja, geht aber alles nur über Timeout.

              Diese TCP-Verbindung steht (sofern sie nicht abgebrochen wird) während des gesamten Austauschs von Anfrage und Antwort und, bei keep-alive-HTTP-Verbindungen, auch noch für weitere Anfrage/Antwort-Pärchen, ähnlich einem Telefongespräch.

              Bitte mit einem mehr oder minder kurzem Zitat aus RFC 2616 belegen, danke.

              Was soll ich belegen? Sorry, aber ich verstehe im Moment wirklich nicht, was Du meinst. Die Netzwerkverbindung besteht während der gesamten Abwicklung von HTTP-Anfrage/Antwort. Das muß sie auch, denn wie soll der Server bitte die Antwort schicken, wenn der Client die Netzwerkverbindung schließt, nachdem er seine Anfrage geschickt hat? Du behauptest doch wohl nicht etwa, daß der Server dann seinerseits eine eigene Netzwerkverbinung zum Client aufbaut?

              Er fragt zumindest nach, ob sie noch besteht. TCP ist genau so ein Hin und Her, wie HTTP. An dieser Stelle mußten die Schreiber von HTTP sehr abstrahieren, so daß sich TCP und HTTP hier ein wenig beißen.

              Es gibt nun mal Kompromisse, die sind nicht die zweitbeste Lösung, sondern weit darunter. TCP ist einer davon.
              IPv6 übrigens ein weiterer *grmpf*

              Um's mit dem Telefonbeispiel darzustellen: Deiner Ansicht nach rufst Du also Deine Freundin an, stellst eine Frage, legst auf und dann ruft Deine Freundin Dich an, um Dir zu antworten?! Mit Verlaub, das ist doch Unfug. Und auch ein Gespräch ist doch wohl für Dich nicht beendet, wenn Du Deine letzte Frage gestellt hast, sondern erst dann, wenn Du zur Frage die Antwort bekommen hast (oder der Gesprächspartner das Zimmer verlässt).

              Hatte ich nicht erwähnt, das der Vergleich stark hinkt? Und hier ist die Schadensstelle. TCP ist nur das Protokoll, das in Deinem Bild die elektomagnetischen Wellen beschreiben würde. Die Leitung legen andere.

              Und jetzt auch noch aus RFC 1122
              Aha, dacht' ich mir ;-)

              Bitte drück dich etwas klarer aus und beschreibe, wie Du das Zusammenspiel von TCP und HTTP zwischen Server und Client siehst, danke. Die "Ich weiß es man besser, aber ich sag's Dir nicht, ätschibätsch"-Schiene finde ich jedenfalls nicht sehr erhellend :/

              Mir schien, das Du Dich damit gut auskennst. Zumindest machten Deine Einwürfe den Eindruck, daß Dir beide Protokolle gut geläufig sind. Daraus folgt natürlich dann, daß Dir auch die Wiedersprüche zwischen TCP und HTTP geläufig sind. Das ist oft genug diskutiert worden. Ergo hatte ich mir erlaubt, nur darauf hinzuweisen, ohne langatmige Erklärungen.

              Ich hoffe Du kannst jetzt nachvollziehen, warum sich manch'

              Nein, solange Du in Rätseln sprichst, kann ich Deine Sicht der Dinge nicht nachvollziehen.

              Du stellst also erst die Verbindung her, indem Du den Telefonhörer abhebst und wählst, und wenn die Verbindung steht (bis hier hin TCP), kommunizierst Du mit der "Gegenstelle" (HTTP). Die "HTTP-Verbindung" kannst Du zu jeder beliebigen Zeit abbrechen, indem Du den Telefonhörer auflegst.

              Aha, hier hakt das Bild. Nach HTTP würdest Du einfach mit dem Sprechen aufhören. Ob Du auflegst interessiert HTTP nicht mehr. Das muß der Browser (Im HTTP heißt er ganz allgemein "User Agent", kann ja auch LWP::Simple sein, o.ä.) bzw der Server dann erledigen.

              Ja, und? Die Verbindung zwischen Webserver und -client besteht nunmal aus der _Einheit_ TCP und HTTP. HTTP führt übrigens kein Eigenleben, es wird vom Browser angewendet. Insofern kann es sich nicht garicht "für irgendetwas interessieren", der einzige Interessierte ist der Browser, und der sieht sowohl seine HTTP-Anfrage als auch seine Netzwerkverbindung.

              Nein, er nutzt die Netzverbindung nur, er sieht sie aber nicht.
              HTTP braucht zur Funktion nur einen Gegenspieler und eine Verbnindung dazu, kein spezielles Netz.
              Du kannst also sagen, das HTTP eine Verbindung braucht. Wie diese aussieht, ist aber völlig egal, Postkarten würden reichen.
              Selbst TCP ist abstrakt genug, auch hier würden Postkarten reichen.

              So, und noch zwei der gewünschten Zitate aus RFC 2616, 8.1.4, "Practical Considerations":

              "A client, server, or proxy MAY close the transport connection at
                 any time."

              "This means that clients, servers, and proxies MUST be able to
                 recover from asynchronous close events."

              Alles andere wäre vom Design her auch ganz großer Mist, dazu sind solche Verbindungen einfach zu unsicher.

              Das Dumme ist nur, das das alles über Timouts geregelt wird, falls die Verbindung wirklich abgebrochen wird und nicht regulär beendet.

              Um in Deinem Bild zu bleiben:

              • Der eine legt einfach auf, der andere bekommt das nicht mit, irgendwann wird's ihm aber zu bunt und er legt auch auf.
              • Der eine sagt:"Denn mal bis die Tage" und legt auf, der andere bekommt das nicht mit, irgendwann wird's ihm aber zu bunt und er legt auch auf.
              • Der eine legt auf, es klackt und tutet beim anderen, das sagt ihm, das der eine aufgelegt hat, flucht einmal kurz über die Unsitten der Jugend und legt selber auf.

              so short

              Christoph Zurnieden

              1. IMHO ist das aber kein Grund, aufwendige Javascript/Session/Sonstwas-Abbruchkonstruktionen zu basteln. Denn _sowas_ führt meiner Erfahrung nach nur zu mehr Problemen als das es welche löst. Wie Du bereits sagtest: es gibt "zuviele Clients als das man sich [..] auf irgendetwas verlassen könnte" - da nehme ich doch lieber den einfachsten Weg.

                Ich fand das den einfachsten Weg (den über Sessions)
                Wenn Du etwas Einfacheres hast: nur raus damit!
                Ich wäre der Letzte, der sowas nicht begrüßen würde.

                Wie gesagt, mod_fastcgi spuckt ein Signal aus, wenn versucht wird, in eine bereits geschlossene Verbindung zu schreiben. Damit kann man zwar leider nicht exakt synchron mit dem Ereignis selber beenden, aber ein Leerzeichen alle x Durchläufe (oder was auch immer das Skript macht) tut IMHO niemandem weh.

                Wer unbedingt die Rechenleistung braucht, die in diesen wenigen Sekunden Verzögerung vom Skript "nutzlos" verbraten wird, sollte sich vielleicht Gedanken darüber machen, ob er die richtige Hardware für sein Vorhaben auf dem Tisch stehen hat.

                Das Problem bei TCP ist nur, das die Verbindung _aktiv_ geschlossen werden muß.
                Ansonsten kann nur ein Timeout greifen.

                Keine Ahnung auf welchen Timeout Du Dich beziehst, aber spätestens wenn Du versuchst, in eine geschlossene Verbindung zu schreiben, kriegst Du ein's auf den Deckel. Man muß diesen, oben bereits beschrieben "Test" also nur serverseitig entsprechend realisieren. Sollte nicht so schwer sein.

                HTTP hat mit der darunterliegenden Netzwerkverbindung TCP absolut garnichts zu tun. HTTP sieht keinen "Befehl" zum unerwarteten Beenden einer Verbindung vor, das stimmt. Das ist auch nicht nötig, weil man einfach die Netzwerkverbindung (TCP) beendet.

                Schön, aber wie machst Du es mit einem Browser?

                Stopp drücken oder Seite wechseln. Wenn ich eine riesige Datei runterlade und mittendrin Stopp drücke, hört die Übertragung sofort auf und meine Mikro-Firewall zeigt die Verbindung als geschlossen an (genauer: zeigt sie nicht mehr an) -> Ziel erreicht.
                Was ist denn daran so schwierig?

                So ist es auch in der HTTP-Spezifikation dokumentiert und mit mehr oder weniger unerwartet abbrechenden Verbindungen sollte im übrigen jede Netzwerkapplikation schon von Natur aus rechnen.

                Ja, und? Die Verbindung zwischen Webserver und -client besteht nunmal aus der _Einheit_ TCP und HTTP. HTTP führt übrigens kein Eigenleben, es wird vom Browser angewendet. Insofern kann es sich nicht garicht "für irgendetwas interessieren", der einzige Interessierte ist der Browser, und der sieht sowohl seine HTTP-Anfrage als auch seine Netzwerkverbindung.

                Nein, er nutzt die Netzverbindung nur, er sieht sie aber nicht.
                HTTP braucht zur Funktion nur einen Gegenspieler und eine Verbnindung dazu, kein spezielles Netz.
                Du kannst also sagen, das HTTP eine Verbindung braucht. Wie diese aussieht, ist aber völlig egal, Postkarten würden reichen.

                Mit Verlaub, das ist als Begründung für einen aufwendigen CGI-Abbruch über Sessionprüfungen etwas sehr weit aus der Theorie hergeholt.

                Es würde mich doch ein wenig wundern, wenn irgendeine HTTP-Anwendung allen Ernstes so geschrieben wurde, daß die HTTP-Schicht keine Ahnung von der Transportschicht hat und insbesondere nichts vom Beenden der Transportverbindung mitbekommen würde.
                Es wäre doch völliger Quatsch, wenn man Kontrollnachrichten der Transportschicht nicht verarbeitet bzw. in die Bearbeitung bei der HTTP-Schicht mit einbezieht.
                Diese Vorgehensweise hätte etwas von einem Auto, in dem die Insassen erst mitbekommen, daß sie wegen leerem Tank wohl nicht am Ziel ankommen werden, nachdem die Karre zehn Minuten lang regungslos auf der Autobahn gestanden hat..

                Anderes Praxisbeispiel:

                Wenn ich mich per telnet an einen HTTP-Server klemme, dann sagt telnet mir automatisch und ohne Zeitverzögerung, daß die Verbindung getrennt wurde, sobald der Server seine Antwort geschickt hat.
                So. Wo ist denn bitte da die relevante Eieruhr, um die Du Dich sorgst? Für mich sieht das jedenfalls so aus, als wenn telnet, das ja nun unwiderlegbar keinerlei Ahnung davon hat, daß ich es für HTTP mißbrauche, von dem Verbindungsabbruch von Seiten des Webservers auf irgendeine Art und Weise informiert wurde, und zwar innerhalb weniger Zehntelsekunden.
                Warum soll das mit anderen Anwendungen nicht auch funktionieren?

                Aus RFC 793, 3.5, "Closing a [TCP] connection", lese ich davon mal abgesehen, daß TCP durchaus eine geordnete Möglichkeit vorsieht, eine Verbindung zu beenden, namentlich mittels FIN- und CLOSE-Segmenten, nicht mittels "seit fünf Minuten kein Bit auf der Leitung".
                Somit sollte es für den TCP-Stack (zumindest theoretisch) kein Problem sein, die Anwendung von einer geschlossenen Verbindung unverzüglich zu informieren und diese sollte daraufhin auch in der Lage sein, ihre Aktivitäten unverzüglich zu beenden. Das hat mit HTTP letztenendes garnichts mehr zu tun.

                Also ich sehe das Zeitproblem immernoch nicht.

                Gruß,
                  soenk.e

                1. Hallo,

                  IMHO ist das aber kein Grund, aufwendige Javascript/Session/Sonstwas-Abbruchkonstruktionen zu basteln. Denn _sowas_ führt meiner Erfahrung nach nur zu mehr Problemen als das es welche löst. Wie Du bereits sagtest: es gibt "zuviele Clients als das man sich [..] auf irgendetwas verlassen könnte" - da nehme ich doch lieber den einfachsten Weg.

                  Ich fand das den einfachsten Weg (den über Sessions)
                  Wenn Du etwas Einfacheres hast: nur raus damit!
                  Ich wäre der Letzte, der sowas nicht begrüßen würde.

                  Wie gesagt, mod_fastcgi spuckt ein Signal aus, wenn versucht wird, in eine bereits geschlossene Verbindung zu schreiben. Damit kann man zwar leider nicht exakt synchron mit dem Ereignis selber beenden, aber ein Leerzeichen alle x Durchläufe (oder was auch immer das Skript macht) tut IMHO niemandem weh.

                  Höchstens dem Geldbeutel.

                  Wer unbedingt die Rechenleistung braucht, die in diesen wenigen Sekunden Verzögerung vom Skript "nutzlos" verbraten wird, sollte sich vielleicht Gedanken darüber machen, ob er die richtige Hardware für sein Vorhaben auf dem Tisch stehen hat.

                  Das liegt schonlange nicht mehr ander Hardware, sondern am Durchsatz. Transfer ist heutztage das Teure.
                  Selbst so ein Leerzeichen kann sich summieren übers Jahr. Wenn die Paketgröße bei den jetzt üblichen ~1500 Bit liegt ...

                  Das Problem bei TCP ist nur, das die Verbindung _aktiv_ geschlossen werden muß.
                  Ansonsten kann nur ein Timeout greifen.

                  Keine Ahnung auf welchen Timeout Du Dich beziehst, aber spätestens wenn Du versuchst, in eine geschlossene Verbindung zu schreiben, kriegst Du ein's auf den Deckel. Man muß diesen, oben bereits beschrieben "Test" also nur serverseitig entsprechend realisieren. Sollte nicht so schwer sein.

                  Es geht aber nicht um den Server, sondern um den Client. Von da aus gibt es nicht viele Möglichkeiten.

                  HTTP hat mit der darunterliegenden Netzwerkverbindung TCP absolut garnichts zu tun. HTTP sieht keinen "Befehl" zum unerwarteten Beenden einer Verbindung vor, das stimmt. Das ist auch nicht nötig, weil man einfach die Netzwerkverbindung (TCP) beendet.

                  Schön, aber wie machst Du es mit einem Browser?

                  Stopp drücken oder Seite wechseln. Wenn ich eine riesige Datei runterlade und mittendrin Stopp drücke, hört die Übertragung sofort auf und meine Mikro-Firewall zeigt die Verbindung als geschlossen an (genauer: zeigt sie nicht mehr an) -> Ziel erreicht.
                  Was ist denn daran so schwierig?

                  Das der Server davon evt nichts mitbekommt. Meistens ist das ordentlich implementiert und die Verbindung wird ordnungsgemäß nach TCP beendet, aber eben nur meistens.
                  Das es bei Dir so ist, heißt nicht, das es überall so ist.
                  Was machst Du außerdem, wenn Du diverse Forks laufen hast? Das kann auch eine Subshell sein, nicht zwingend ein reguläres Child. Die rennt dann weiter, wenn sie nicht abgeschossen wird.

                  So ist es auch in der HTTP-Spezifikation dokumentiert und mit mehr oder weniger unerwartet abbrechenden Verbindungen sollte im übrigen jede Netzwerkapplikation schon von Natur aus rechnen.

                  Ja, und? Die Verbindung zwischen Webserver und -client besteht nunmal aus der _Einheit_ TCP und HTTP. HTTP führt übrigens kein Eigenleben, es wird vom Browser angewendet. Insofern kann es sich nicht garicht "für irgendetwas interessieren", der einzige Interessierte ist der Browser, und der sieht sowohl seine HTTP-Anfrage als auch seine Netzwerkverbindung.

                  Nein, er nutzt die Netzverbindung nur, er sieht sie aber nicht.
                  HTTP braucht zur Funktion nur einen Gegenspieler und eine Verbnindung dazu, kein spezielles Netz.
                  Du kannst also sagen, das HTTP eine Verbindung braucht. Wie diese aussieht, ist aber völlig egal, Postkarten würden reichen.

                  Mit Verlaub, das ist als Begründung für einen aufwendigen CGI-Abbruch über Sessionprüfungen etwas sehr weit aus der Theorie hergeholt.

                  "Über 90% der Surfer nutzen den IE, warum soll ich mich für die restlichen paar Prozente abmühen?"

                  Ne ne, Herr Kollege, so nicht! ;-)

                  Das ursprüngliche Problem war, auch wenn sich der Threadinitiator schon längst sehr irritiert zurückgezogen hat, vom Client aus aktiv(!) dem Server ein Signal zum Abbruch eines vorher vom selbem Client angestoßenen Prozesses zu übermitteln. Da der Client sich mit dem Server über HTTP unterhält, war die einzige Möglichkeit, die mir einfiel eben jene: mittels SessionID alle Mittäter zu identifizieren und dadurch eine Möglichkeit zu schaffen den fraglichen Prozess zu killen.
                  Alles andere ist nicht sicher genug und selbst meine Methode hat einige Schwachstellen.
                  Nur vom Server aus wäre es möglich, den Client regelmäßig "anzupingen" um sein Interesse nachzuprüfen. Bei länger andauernden Serverprozessen, z.B. die Volltextsuche in Terabytedatenbanken o.ä., wäre das sogar zu empfehlen, um ein evt Timeout auf Clientseite zu verhindern.

                  Es würde mich doch ein wenig wundern, wenn irgendeine HTTP-Anwendung allen Ernstes so geschrieben wurde, daß die HTTP-Schicht keine Ahnung von der Transportschicht hat und insbesondere nichts vom Beenden der Transportverbindung mitbekommen würde.

                  Tut sie auch nicht, dafür sind andere zuständig.
                  Sollten zumindest ;-)

                  Es wäre doch völliger Quatsch, wenn man Kontrollnachrichten der Transportschicht nicht verarbeitet bzw. in die Bearbeitung bei der HTTP-Schicht mit einbezieht.

                  Das wiederspräche aber der so heiß und innig geliebten Objektorientiertheit. >;->

                  Diese Vorgehensweise hätte etwas von einem Auto, in dem die Insassen erst mitbekommen, daß sie wegen leerem Tank wohl nicht am Ziel ankommen werden, nachdem die Karre zehn Minuten lang regungslos auf der Autobahn gestanden hat..

                  Beinahe hätte ich gesagt, daß dieser Vergleich nicht nur hinkt, sondern sogar schon im Rollstuhl sitzt, aber ich kenne da einen ADAC Straßenwachtfahrer: Sowas gibt es öfters als man annimmt.

                  Anderes Praxisbeispiel:

                  Wenn ich mich per telnet an einen HTTP-Server klemme, dann sagt telnet mir automatisch und ohne Zeitverzögerung, daß die Verbindung getrennt wurde, sobald der Server seine Antwort geschickt hat.

                  Ja, denn Telnet hängt etwas mehr an TCP. Das HTTP besorgst Du da ja händisch.

                  So. Wo ist denn bitte da die relevante Eieruhr, um die Du Dich sorgst? Für mich sieht das jedenfalls so aus, als wenn telnet, das ja nun unwiderlegbar keinerlei Ahnung davon hat, daß ich es für HTTP mißbrauche, von dem Verbindungsabbruch von Seiten des Webservers auf irgendeine Art und Weise informiert wurde, und zwar innerhalb weniger Zehntelsekunden.

                  Es wird nach TCP die Verbindung beendet. Das _muß_ nach Telnet Protokol beachtet werden, deshalb tut telnet das auch. (Ach, wenn doch auch die Browser sich daran halten würden: "... muß nach HTTP, deswegen macht der Browser das auch so"  *sigh* )

                  Warum soll das mit anderen Anwendungen nicht auch funktionieren?

                  Andere Protokolle?

                  Aus RFC 793, 3.5, "Closing a [TCP] connection", lese ich davon mal abgesehen, daß TCP durchaus eine geordnete Möglichkeit vorsieht, eine Verbindung zu beenden, namentlich mittels FIN- und CLOSE-Segmenten, nicht mittels "seit fünf Minuten kein Bit auf der Leitung".

                  Ja (Das meinte ich übrigens mit "sauber beenden"), aber lies mal weiter:

                  The normal TCP close sequence delivers buffered data
                  reliably in both directions.  Since the two directions of a
                  TCP connection are closed independently, it is possible for
                  a connection to be "half closed," i.e., closed in only one
                  direction, and a host is permitted to continue sending data
                  in the open direction on a half-closed connection.

                  [es folgen noch eine Sätze, die allerdings durch die Benutzung von MAY und SHOULD relativiert werden]

                  Klingt eindeutig? Na, dann schau Dir mal einige der Implementierungen an.

                  Somit sollte es für den TCP-Stack (zumindest theoretisch) kein Problem sein, die Anwendung von einer geschlossenen Verbindung unverzüglich zu informieren und diese sollte daraufhin auch in der Lage sein, ihre Aktivitäten unverzüglich zu beenden. Das hat mit HTTP letztenendes garnichts mehr zu tun.

                  Deshalb läßt es sich auch für das Problem nicht benutzen.

                  Das es kein Problem darstellt, jemanden zu informieren heißt leider noch lange nicht, das es auch getan wird. Siehe auch die derzeitigen Problem an der Elbe und Umgebung.

                  Also ich sehe das Zeitproblem immernoch nicht.

                  Das Timeoutproblem entsteht nur, wenn _nicht_ ordnungsgemäß geschlossen wurde.
                  Das passiert aber leider häufiger, als nötig.

                  so short

                  Christoph Zurnieden

        3. Hi Sönke,

          Falls Du Ausgaben meinst: Es hängt doch wohl vom
          Skript/Programm ab, wann es etwas ausgibt.
          Warum sollte es beispielsweise nicht als erstes
          den Seitenkopf ausgeben, dann seine Berechnungen
          durchführen, während dieser Berechnungen schon
          Teilergebnisse ausgeben und am Ende nochmal den
          Seitenfuß hinterherschicken. Dann wird während der
          gesamten Laufzeit des Skriptes etwas ausgegeben.

          weil im Seitenkopf etwas stehen kann, das erst als
          Ergebnis der gesamten Berechnung entsteht.

          Bei HTTP ist dies beispielsweise die Content-Length.
          _Wenn_ Du eine solche senden willst (statt Dir über
          "chunked" transfer encoding zu behelfen), dann _mußt_
          Du das gesamte Paket aufsammeln, seine Länge berechnen
          und _zuerst_ die HTTP-Header und _danach_ den Content
          senden. Anders herum geht es nicht.

          Insofern verstehe ich nicht, warum "das CGI meist
          schon fertig" sein soll? Entsprechend obigem Ablauf
          würde ich glatt das genaue Gegenteil behaupten.
          Skripte geben eher nur in Ausnahmefällen einzig
          kurz vorm Beenden etwas aus. Da müsste man ja
          umständlicherweise sämtliche Ausgaben zwischendurch
          sammeln - diese Mühe werden sich meiner Einschätzung
          nach eher die wenigsten machen (sofern nicht schon
          eine Puffer-Automatik eingebaut ist).

          Das macht auch nicht das Skript, sondern der Webserver!
          Der muß ja ohnehin nachsehen, ob er fehlende HTTP-
          Header ergänzen muß oder was auch immer.

          Noch ein Fall, wo zwischen Skript und Leitung gepuffert
          wird: mod_gzip.
          Das gzip-Verfahren eignet sich nicht dafür, streams zu
          komprimieren - das kann nur Dateien verarbeiten.
          Der Apache sammelt brav die Ausgabe eines CGI-Skripts,
          einer SSI-Datei etc. auf und sendet diese nicht einfach
          auf die Leitung, sondern macht daraus "chunks".
          mod_gzip bekommt die ganze Ladung chunks auf den Tisch,
          löscht die zusätzlichen chunk-Informationen wieder
          heraus, wandelt das alles in ein einziges response-
          Paket um und _jetzt_ wird der Inhalt komprimiert und
          _danach_ ... nein, immer noch nicht auf die Leitung
          geschrieben, sondern erst mal zurück in einen Apache-
          Puffer (da könnten ja noch andere kommen, die ihren
          Senf dazu geben müssen).

          Ich kenne nur ein einziges Apache-Modul, das vorbei
          an allen guten Sitten direkt auf die Leitung schreibt:
          mod_ssl. Deshalb funktionieren mod_ssl und mod_gzip
          auch nicht zusammen (jedenfalls nicht so, wie das bei
          allen anderen Modul-Kombinationen geht, sondern in
          diesem Fall nur von hinten durch die Brust ins Auge,
          d. h. mit mod_proxy als 'Brücke').

          Viele Grüße
                Michael