Felix Riesterer: ignore_user_abort() - geht auch "send_server_abort()"?

Liebe Forumler,

ich möchte, dass ein Script seinen HTML-Output komplett an den Browser ausliefert, diesen dann nach Hause schickt, um alleine noch eine Aufgabe zu erledigen.

Was ich mit ignore_user_abort() erreiche, ist ein Warten des Browsers, bis das Script sich beendet hat, obwohl er an HTML-Output schon alles empfangen hat.

Wie erreiche ich, dass das Script dem Browser zu verstehen gibt, dass er schon fertig ist? In der Doku sind nur Beispiele, die von der anderen Seite her (Userabbruch) argumentieren...

Liebe Grüße aus Ellwangen,

Felix Riesterer.

  1. hi,

    ich möchte, dass ein Script seinen HTML-Output komplett an den Browser ausliefert, diesen dann nach Hause schickt, um alleine noch eine Aufgabe zu erledigen.

    Wie meinen?
    Wer schickt wen wohin?

    Was ich mit ignore_user_abort() erreiche, ist ein Warten des Browsers, bis das Script sich beendet hat, obwohl er an HTML-Output schon alles empfangen hat.

    Nein, was du mit ignore_user_abort erreichst ist, dass dein Script auch dann noch zuende läuft, wenn der Client bereits signalisiert hat - durch Abbruch der Verbindung - "komm, lass stecken - das dauert mir alles zu lange".

    Wie erreiche ich, dass das Script dem Browser zu verstehen gibt, dass er schon fertig ist?

    Ich vermute, du suchst flush() und Co.?

    Beschäftige dich mit den Funktionen zur Ausgabesteuerung

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Lieber wahsaga,

      Ich vermute, du suchst flush() und Co.?

      Beschäftige dich mit den Funktionen zur Ausgabesteuerung

      danke für die Links. Soweit war ich aber schon.

      Mein Script hält mit ob_start() die Ausgaben zurück, echo-t ein HTML-Dokument, macht einen ob_end_flush(), wodurch der Browser allen HTML-Code erhält (inclusive verschiedener Header unterwegs). Nun soll der Browser zufrieden die Verbindung trennen und beim Benutzer das Dokument rendern (also window.onload feuern), während mein Script noch eine etwas zeitintensive Operation ausführt, um eine SESSION-Variablen zu befüllen und sich dann zu beenden.

      Was passiert? Der Browser hat alles bekommen, was er soll, wartet aber mit dem Rendern der Seite, bis mein Script seine zeitintensive Operation beendet hat. Rendern bedeutet, dass da ein Javascript einen WYSIWYG-Editor (TinyMCE) starten soll, welches erst bei vollständig geladenem Dokument loslegt. Solange mein PHP-Script aber noch arbeitet, hält der Browser die Verbindung, obwohl keine Daten mehr gesendet werden (flush() war ja schon).

      Wie kann ich ihm das Warten abgewöhnen?

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

      1. hi,

        Solange mein PHP-Script aber noch arbeitet, hält der Browser die Verbindung, obwohl keine Daten mehr gesendet werden (flush() war ja schon).

        Wie kann ich ihm das Warten abgewöhnen?

        Ui, das weiß ich auch nicht - eine direkte Möglichkeit in PHP, die Verbindung zu schließen, bzw. die Datenübertragung explizit für beendet zu erklären, und danach noch weiteren Scriptcode auszuführen, ist mir nicht bekannt.

        Du bräuchtest also vermutlich so etwas wie einen unabhängigen/neuen Thread, welchen du vom "alten" Thread - eben den, der den aktuellen Request bearbeitet hat - angestoßen wird, und dann unabhängig von diesem weiterläuft.

        Mit sowas habe ich in PHP aber auch keine Erfahrung, vermute aber es ist kompliziert.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Lieber wahsaga,

          Du bräuchtest also vermutlich so etwas wie einen unabhängigen/neuen Thread, welchen du vom "alten" Thread - eben den, der den aktuellen Request bearbeitet hat - angestoßen wird, und dann unabhängig von diesem weiterläuft.

          das habe ich befürchtet.

          Mit sowas habe ich in PHP aber auch keine Erfahrung, vermute aber es ist kompliziert.

          In den User-Comments zu ignore_user_abort() hat jemand veröffentlicht, wie er mit einem socket eine neue Resource anfordert, und so einen zusätzlichen thread erzeugt. Muss das mal studieren. Mit diesen socket-Sachen bin ich absolut nicht der Held.

          Liebe Grüße aus Ellwangen,

          Felix Riesterer.

          1. Hallo Felix,

            es gibt einen Trick wie man in manchen Fällen genau das bewirken kann. Wenn du die Content-Lenght (header) mitlieferst, verarbeiten manche Browser nur diese Länge und brechen danach die Verbindung ab oder betrachten zumindest das danach empfangene nicht mehr.

            Chris

            1. Lieber Chris,

              Danke für den Tipp. Werde ich ausprobieren.

              Liebe Grüße aus Ellwangen,

              Felix Riesterer.

              1. Also,

                das mitschicken eines "Content-Length"-Headers hält den Browser auch nicht vom Warten ab. :-(

                Liebe Grüße aus Ellwangen,

                Felix Riesterer.

                1. Da überkommt mich so eine Skepsis...

                  das mitschicken eines "Content-Length"-Headers hält den Browser auch nicht vom Warten ab. :-(

                  Für die Ermittlung der Content-Length verwende ich strlen(ob_get_contents()). Da sind meines Wissens die Header nicht mit eingerechnet. Ist das so korrekt verwendet?

                  // Header mit Content-Length ausgeben (ermittelt aus dem Output-Buffer)  
                  header('Content-Length: '.strlen(ob_get_contents()));
                  

                  Und wie überprüfe ich (lokal!), ob die korrekte Content-Length auch tatsächlich ermittelt wurde? Der FF sagt unter "Seiten-Informationen" dasselbe, wie mit seiner Webdeveloper-Extension unter Informationen->Response-Header. Aber wie prüfe ich das (lokal!) genauer?

                  Liebe Grüße aus Ellwangen,

                  Felix Riesterer.

                  1. echo $begrüßung;

                    Für die Ermittlung der Content-Length verwende ich strlen(ob_get_contents()). Da sind meines Wissens die Header nicht mit eingerechnet. Ist das so korrekt verwendet?

                    // Header mit Content-Length ausgeben (ermittelt aus dem Output-Buffer)

                    header('Content-Length: '.strlen(ob_get_contents()));

                      
                    Ja, es heißt ja auch Content-Length und nicht Response-Length. :-) strlen() liefert dir das richtige Ergebnis, solange PHP Multibyte-Zeichen noch nicht richtig auswertet. Aber die Wahrscheinlichkeit, dass du die [Multibyte String Extension](http://de.php.net/manual/en/ref.mbstring.php) oder schon PHP 6 einsetzt, ist doch eher als gering einzuschätzen.  
                      
                    
                    > Und wie überprüfe ich (lokal!), ob die korrekte Content-Length auch tatsächlich ermittelt wurde? Der FF sagt unter "Seiten-Informationen" dasselbe, wie mit seiner Webdeveloper-Extension unter Informationen->Response-Header. Aber wie prüfe ich das (lokal!) genauer?  
                      
                    Ich verstehe nicht, was du damit genau meinst. Vielleicht durch Speichern und Dateilänge nachschauen?  
                      
                      
                    echo "$verabschiedung $name";
                    
                    1. Lieber dedlfix,

                      Ja, es heißt ja auch Content-Length und nicht Response-Length. :-) strlen() liefert dir das richtige Ergebnis, solange PHP Multibyte-Zeichen noch nicht richtig auswertet.

                      das habe ich mir auch gedacht, aber im Forum gibt es (fast) immer jemanden, der/die sich da besser auskennt.

                      Aber die Wahrscheinlichkeit, dass du die Multibyte String Extension oder schon PHP 6 einsetzt, ist doch eher als gering einzuschätzen.

                      Ist definitiv weder bei meinem Hoster, noch bei mir der Fall.

                      Und wie überprüfe ich (lokal!), ob die korrekte Content-Length auch tatsächlich ermittelt wurde? Der FF sagt unter "Seiten-Informationen" dasselbe, wie mit seiner Webdeveloper-Extension unter Informationen->Response-Header. Aber wie prüfe ich das (lokal!) genauer?

                      Ich verstehe nicht, was du damit genau meinst. Vielleicht durch Speichern und Dateilänge nachschauen?

                      Dabei bekomme ich im FF unter Seiteninformationen -> Größe "nicht angegeben". Die Dateieigenschaften unter Windoof Explorer behaupten definitiv mehr Bytes, als die Content-Length, aber das könnte auch an einem Overhead des Dateisystems liegen...

                      Liebe Grüße aus Ellwangen,

                      Felix Riesterer.

                      1. Hallo Felix,

                        Die Dateieigenschaften unter Windoof Explorer behaupten definitiv mehr Bytes, als die Content-Length, aber das könnte auch an einem Overhead des Dateisystems liegen...

                        nein, das ist nicht der Fall.
                        Natürlich gibt es einen gewissen Verwaltungs-Overhead im Filesystem (Verzeichniseintrag, FAT bzw. NTFS File Tables), aber der wird nicht der Dateigröße zugerechnet. Als Dateigröße gibt Windows nur die Menge an Nutzdaten an, den reinen Content.

                        Aber dass die angezeigte Dateigröße mehr angibt als Content-Length, kommt mir dennoch merkwürdig vor. Oder gibt Content-Length womöglich die für die Übertragung komprimierte Größe an?

                        Schönen Tag noch,
                         Martin

                        --
                        Wenn alle das täten, wass sie mich können,
                        käme ich gar nicht mehr zum Sitzen.
                        1. Hi,

                          Aber dass die angezeigte Dateigröße mehr angibt als Content-Length, kommt mir dennoch merkwürdig vor. Oder gibt Content-Length womöglich die für die Übertragung komprimierte Größe an?

                          Content-Length bezieht sich auf das, was zum Server übertragen wird.
                          Die Dateigröße auf das, was tatsächlich abgespeichert wird, was oft nicht identisch mit dem übertragenen ist (z.B. tbody, die automatisch eingefügt werden; bei "Komplette Seite speichern" diverse Kommentare, geänderte Bild-/CSS-/Script-Pfade; ggf. auch Zeilenenden, die von \n auf \r\n geändert wurden usw.)

                          cu,
                          Andreas

                          --
                          Warum nennt sich Andreas hier MudGuard?
                          Schreinerei Waechter
                          O o ostern ...
                          Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
                          1. Hallo,

                            Content-Length bezieht sich auf das, was zum Server übertragen wird.
                            Die Dateigröße auf das, was tatsächlich abgespeichert wird, was oft nicht identisch mit dem übertragenen ist (z.B. tbody, die automatisch eingefügt werden; bei "Komplette Seite speichern" diverse Kommentare, geänderte Bild-/CSS-/Script-Pfade; ggf. auch Zeilenenden, die von \n auf \r\n geändert wurden usw.)

                            ah, daran habe ich nicht gedacht. Ja, logisch, danke für den Hinweis - es ist natürlich ein Unterschied, ob der Original-Quellcode gespeichert wird oder der "Generated Source".

                            Ciao,
                             Martin

                            --
                            Dieser Satz wurde in mühsamer Kleinstarbeit aus einzelnen Wörtern zusammengesetzt.
                              (Hopsel)
          2. Hi Felix,

            In den User-Comments zu ignore_user_abort() hat jemand veröffentlicht, wie er mit einem socket eine neue Resource anfordert, und so einen zusätzlichen thread erzeugt. Muss das mal studieren. Mit diesen socket-Sachen bin ich absolut nicht der Held.

            Sockets dienen zur Kommunikation von Prozessen unter Linux - das brauchst du hier so wie ich das sehe nicht. Meines Erachtens hast du hier zwei Möglichkeiten:

            1. Das PHP-Script forked sich, so dass du dann zwei PHP-Prozesse hast, der erste geht einfach zu Ende und der zweite arbeitet unabhängig vom User noch weiter. Mathias hat dir den Link meines damaligen Threads schon gepostet - im zweiten Thread dazu ist auch mein komplettes Script veröffentlicht. Allerdings geht diese Methode nur, wenn die PHP-Extension pcntl installiert wurde, dafür lernst du aber mal was richtiges[tm] ;-)

            2. Die vielleicht schnellere Methode wäre mal ein fclose(STDIN); fclose(STDOUT); fclose(STDERR); auszuprobieren - wenn du Glück hast ist für den Apache der PHP-Prozess damit fertig und der Apache schließt die Verbindung.

            MfG, Dennis.

            --
            Mein SelfCode: ie:{ fl:( br:> va:) ls:[ fo:) rl:( n4:# ss:) de:] js:| ch:{ sh:| mo:} zu:|
            Patch zur Verwendung von PATHINFO in JLog
            Das Denken ist zwar allen Menschen erlaubt, aber vielen bleibt es erspart. (Curt Goetz)
            1. Lieber Dennis,

              zwei Möglichkeiten:

              1. Das PHP-Script forked sich, so dass du dann zwei PHP-Prozesse hast, der erste geht einfach zu Ende und der zweite arbeitet unabhängig vom User noch weiter. Mathias hat dir den Link meines damaligen Threads schon gepostet - im zweiten Thread dazu ist auch mein komplettes Script veröffentlicht. Allerdings geht diese Methode nur, wenn die PHP-Extension pcntl installiert wurde, dafür lernst du aber mal was richtiges[tm] ;-)

              mann, das wird ja immer krasser! Muss ersteinmal prüfen, ob die benötigte Erweiterung überhaupt verfügbar ist. - Ich denke, ich möchte es lieber ohne diese Erweiterung realisieren... wenn das geht.

              1. Die vielleicht schnellere Methode wäre mal ein fclose(STDIN); fclose(STDOUT); fclose(STDERR); auszuprobieren - wenn du Glück hast ist für den Apache der PHP-Prozess damit fertig und der Apache schließt die Verbindung.

              DAS klingt sehr charmant! Das werde ich gleich als erstes ausprobieren!

              Liebe Grüße aus Ellwangen,

              Felix Riesterer.

              1. Hmm...

                1. Die vielleicht schnellere Methode wäre mal ein fclose(STDIN); fclose(STDOUT); fclose(STDERR); auszuprobieren -

                ich finde nirgends einen Hinweis im PHP-Manual, dass solche Konstanten im PHP-Apache-Modul definiert wären... Diese Methode ist wohl nur unter PHP als CLI -Dingens möglich. Bei mir (und auf dem von mir zu betreuenden Webspace) läuft PHP aber als Apache-Modul.

                Liebe Grüße aus Ellwangen,

                Felix Riesterer.

                1. echo $begrüßung;

                  1. Die vielleicht schnellere Methode wäre mal ein fclose(STDIN); fclose(STDOUT); fclose(STDERR); auszuprobieren -

                  ich finde nirgends einen Hinweis im PHP-Manual, dass solche Konstanten im PHP-Apache-Modul definiert wären...

                  Es sind auch keine Konstanten: PHP input/output streams.

                  echo "$verabschiedung $name";

        2. Hallo wahsaga.

          Du bräuchtest also vermutlich so etwas wie einen unabhängigen/neuen Thread, welchen du vom "alten" Thread - eben den, der den aktuellen Request bearbeitet hat - angestoßen wird, und dann unabhängig von diesem weiterläuft.

          Mit sowas habe ich in PHP aber auch keine Erfahrung, vermute aber es ist kompliziert.

          Dennis hatte (soweit ich mich erinnern kann) einmal so etwas gemacht.

          Einen schönen Dienstag noch.

          Gruß, Mathias

          --
          sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
          debian/rules