ichen: Antwort auf Post-Request unvollständig

Hi zusammen!
ich habe da ein Problem, zu dem ich noch nicht so richtig was gefunden habe. Es geht um einen HTTP Post Request den ich mittels PHP absetze und dessen Rückantwort ich komplett in eine Variable geben möchte. Ziel des ganzen ist es, eine Formulareingabe zu simulieren und die Antwortseite des Scripts, welches die Formulardaten verarbeitet in die Variable zu lesen.
Das klappt auch ganz gut, nur dass ich vom Server nur 1440 bzw manchmal auch 2880 Zeichen zurückbekomme (Seite ist eigentlich ca. 42k zeichen lang, die ich auch bekommen möchte!), obwohl ich bei fread() als length 100k angegeben habe. Das verwundert mich schon, und ich weiß nicht woran das liegen könnte. Hier das bisschen Code mit dem ich z.Z. testweise arbeite.

  
$suchstring = "SText=".$fname."&Kat=Titel";  
$fsock = fsockopen($host, 80, $errno, $errstr);  
$data = "POST $path HTTP/1.1\r\n"  
     ."Host: $host \r\n"  
   ."Content-type: application/x-www-form-urlencoded\r\n"  
   ."Content-Length: ".strlen($suchstring)."\r\n\r\n"  
   .$suchstring;  
fputs($fsock,$data);  
$contents = fread ($fsock, 100000);  
fclose ($fsock);  
echo strlen($contents);  
echo "<pre>".htmlspecialchars($contents)."</pre>";  

Vielleicht kann mir ja jemand helfen.
tschau
ichen

--
Ichen
  1. Hello,

    Das klappt auch ganz gut, nur dass ich vom Server nur 1440 bzw manchmal auch 2880 Zeichen zurückbekomme (Seite ist eigentlich ca. 42k zeichen lang, die ich auch bekommen möchte!), obwohl ich bei fread() als length 100k angegeben habe. Das verwundert mich schon, und ich weiß nicht woran das liegen könnte. Hier das bisschen Code mit dem ich z.Z. testweise arbeite.

    Das mit den 100k ist Dein Fehler.

    Ich habe das noch nicht näher untersucht, wieso die URL-Wrapper meistens krachen gehen, wenn man sich auf das automatische Buffering von PHP verlässt...

    Aber nimm eine Schleife:

    $page = '';

    while (! fof($fh))
       {
          $page .= fread($fh, 128);
       }

    fclose($fh);

    Das klappt eigentlich immer.

    Harzliche Grüße aus
    Sankt Andreasberg
    und Guten Rutsch

    Tom

    --
    Nur selber lernen macht schlau

    1. Hi Tom!

      Das mit den 100k ist Dein Fehler.

      Wo ist da ein Fehler? Die Datei ist 42.000 Zeichen lang, ich will bis max. 100.000 auslesen bzw bis EOF...

      Aber nimm eine Schleife:
      [...]
      Das klappt eigentlich immer.

      Hat auch geklappt. Danke.
      tschau
      ichen

      --
      Ichen
      1. Hello,

        Das mit den 100k ist Dein Fehler.

        Wo ist da ein Fehler? Die Datei ist 42.000 Zeichen lang, ich will bis max. 100.000 auslesen bzw bis EOF...

        Formal ist es richtig, aber an dieser Stelle funktioniert es nicht.
        Dedlfix hat Dir die Stelle ja auch zitiert, an der es steht und die beschreibt, warum es nicht funktioniert. fread() hört eben auf zu lesen, wenn das Paket zuende gelesen ist.

        Aber nimm eine Schleife:
        [...]
        Das klappt eigentlich immer.

        Hat auch geklappt. Danke.

        Na, sag ich doch.
        Man müsste eigentlich in der Schleife auch den Rückgabewert von fread() auf !== false (nicht identisch false) prüfen. Wenn nämlich ein Socketfehler auftritt, kann fread() nicht mehr lesen, aber feof() ist nicht erreicht.

        $ok   = true;
        $page = '';

        while (!feof($fh) and $ok)
        {
          $buf = fread($fh, 128);
          if ($buf === false)
          {
            $ok = false;
          }
          else
          {
            $page .= $buf;
          }
        }

        Das ist jetzt etwas umständlich geschrieben. Aber es stellt sicher, dass man nach Abbruch der Schleife noch feststellen kann, warum sie beendet wurde.

        Zusammengeschrumpft müsste es so auch gehen:

        while (!feof($fh))
        {
          if (false === ($buf = fread($fh, 128)) break;
          $page .= $buf;
        }

        Harzliche Grüße aus
        Sankt Andreasberg
        und Guten Rutsch

        Tom

        --
        Nur selber lernen macht schlau

  2. echo $begrüßung;

    Das klappt auch ganz gut, nur dass ich vom Server nur 1440 bzw manchmal auch 2880 Zeichen zurückbekomme (Seite ist eigentlich ca. 42k zeichen lang, die ich auch bekommen möchte!), obwohl ich bei fread() als length 100k angegeben habe. Das verwundert mich schon, und ich weiß nicht woran das liegen könnte.

    Das PHP-Handbuch zu fread() weiß es aber:

    Reading stops as soon as one of the following conditions is met:

    * length bytes have been read
        * EOF (end of file) is reached
        * a packet becomes available (for network streams)
        * 8192 bytes have been read (after opening userspace stream)

    Der dritte Punkt dürfte die Ursache für das von dir beobachtete Verhalten sein.

    echo "$verabschiedung $name";

    1. Hello,

      Das PHP-Handbuch zu fread() weiß es aber:

      Reading stops as soon as one of the following conditions is met:

      * length bytes have been read
          * EOF (end of file) is reached
          * a packet becomes available (for network streams)
          * 8192 bytes have been read (after opening userspace stream)

      Der dritte Punkt dürfte die Ursache für das von dir beobachtete Verhalten sein.

      *uiuiui*
      Die haben aber gewaltig an dem Handbuch gearbeiet. Ich hatte dafür neulich erst eine Begründung gesucht, da stand das noch nicht drin. Also immer eigene Schleife bei Socket-Funktionen benutzen.

      Wier ist das denn bei file_get_contents()? Hat das eine eingebaute Schleife?

      Eigentlich müsste man in der Schleife auch noch den Rückgabewert von fread() abfragen, ob der ggf. === false ist. Dann ist ein Fehler aufgetreten und vermutlich kann man nicht weiterlesen bzw. hängt sich mit while( !feof()) auf, weil man gar nicht auf eof kommt?

      Harzliche Grüße aus
      Sankt Andreasberg
      und Guten Rutsch

      Tom

      --
      Nur selber lernen macht schlau

    2. Hai $name;

      Das PHP-Handbuch zu fread() weiß es aber:
      Reading stops as soon as one of the following conditions is met:
          * length bytes have been read
          * EOF (end of file) is reached
          * a packet becomes available (for network streams)
          * 8192 bytes have been read (after opening userspace stream)
      Der dritte Punkt dürfte die Ursache für das von dir beobachtete Verhalten sein.

      hmm,
      da mein Englisch nicht so toll ist, habe ich zwei Leute, die u.a. von Uebersetzungen(PHP/MySQL) leben, gebeten, mir zu erklaeren, was dort an 3. und 4. Stelle steht. Kam jedoch nix sinnvolles dabei raus, war aber nett, mal wieder mit ihnen telefoniert zu haben. Und da leider auch Google keine sinnvolle Uebersetzung zustande brachte, hoffe ich, dass hier jemand etwas brauchbares dazu posten kann.

      Gruss und Dank
      sowie allen ein gesundes Neues Jahr
      Norbert

      1. echo $begrüßung;

        Das PHP-Handbuch zu fread() weiß es aber:
        Reading stops as soon as one of the following conditions is met:

        Das Lesen endet sobald eine der folgenden Bedingungen zutrifft:

        * length bytes have been read

        length bezieht sich auf den 2 Parameter von fread(), also: $length Bytes wurden gelesen

        * EOF (end of file) is reached

        Das Ende der Datei wurde erreicht.

        * a packet becomes available (for network streams)

        Ein Paket wurde verfügbar, sprich: empfangen (trifft bei Netzwerkverkehr zu)

        * 8192 bytes have been read (after opening userspace stream)

        8192 Bytes wurden gelesen (nach dem Öffnen eines Benutzer-Streams) - trifft in dem Fall nicht zu.

        Der dritte Punkt dürfte die Ursache für das von dir beobachtete Verhalten sein.
        da mein Englisch nicht so toll ist, [...] hoffe ich, dass hier jemand etwas brauchbares dazu posten kann.

        Übersetzung siehe oben. Hier zeigt es sich auch wieder, dass die englische Version des Handbuchs zu bevorzugen ist (so man es verstehen kann), denn in der deutschen fehlt die Erwähnung des dritten (und vierten) Punktes.

        echo "$verabschiedung $name";

        1. Hallo $name,

          * a packet becomes available (for network streams)
          Ein Paket wurde verfügbar, sprich: empfangen (trifft bei Netzwerkverkehr zu)
              * 8192 bytes have been read (after opening userspace stream)
          8192 Bytes wurden gelesen (nach dem Öffnen eines Benutzer-Streams) - trifft in dem Fall nicht zu.

          okay,
          dann habe ich/wir es ja auch richtig interpretiert.
          Wobei dies jedoch den Laengenparameter ueberfluessig macht.
          Was einheitlich mit "das kann nicht sein" verworfen wurde.
          Merke: Du sollst coden und nicht denken!

          Gruss und Happy Dingens
          Norbert

          1. Hello,

            dann habe ich/wir es ja auch richtig interpretiert.
            Wobei dies jedoch den Laengenparameter ueberfluessig macht.

            Nicht ganz. Wenn man z.B. spezielle Dateiformate auslesen will, die ja auch in Peketen verpackt kommen können, dann will man eventuell zuerst nur die ersten 14Bytes lesen. Erst wenn diese ausgewertet sind, weiß man dann z.B. wie lang der secondary header der Datei ist, und ob man die Daten überhaupt haben will.

            Da wäre es doch schon dusselig, sich den gesamten Block mühevoll reinzuholen, um ihn dann doch wieder nur zu zerlegen.

            PHP mischt hier aber quer über seine verschiedenen Lesefunktionen für Dateien oder solche, die es werden sollen, die automatische Pufferung und Quasi-Low-Level-Zugriffe. Das macht einfach keinen Spaß.  Ichen hat sich zu Recht beschwert, als ich schrieb: da hast Du was falsch gemacht mit den 100k.

            Harzliche Grüße aus
            Sankt Andreasberg
            und Guten Rutsch

            Tom

            --
            Nur selber lernen macht schlau

            1. Hallo Tom,

              Da wäre es doch schon dusselig, sich den gesamten Block mühevoll
              reinzuholen, um ihn dann doch wieder nur zu zerlegen.

              na-ja,
              um via fsockopen Daten zu lesen nutze ich immer wieder die gleiche
              uralte Methode, einfach weil sie funktioniert.
              1. Schleife mit fgets() bis zur Leerzeile, fuer die Haeders.
              2. Schleife mit fgets() bis zum feof(), fuer die eigentliche Datei.
              Kann man im aktuellen Script jederzeit mit einer Pruefung beenden.

              Gruss und Happy Dingens
              Norbert

              1. Hello,

                Da wäre es doch schon dusselig, sich den gesamten Block mühevoll
                reinzuholen, um ihn dann doch wieder nur zu zerlegen.

                na-ja,
                um via fsockopen Daten zu lesen nutze ich immer wieder die gleiche
                uralte Methode, einfach weil sie funktioniert.

                1. Schleife mit fgets() bis zur Leerzeile, fuer die Haeders.
                2. Schleife mit fgets() bis zum feof(), fuer die eigentliche Datei.
                  Kann man im aktuellen Script jederzeit mit einer Pruefung beenden.

                Das passt dann aber nur für http
                PHP kann da auch mehr, indem es hier einfach wenig gefiltert hat aus der C-Schicht ;-)

                http://de.php.net/manual/en/transports.php

                Ich bevorzuge es außerdem, sinnvolle Timeout-Werte selber vorgeben zu können und nicht "zeilenweise", sondern tatsächlich blockorientiert zu lesen. Bei http mag das vielleicht ungeschickter sein, aber es funktioniert sicherlich genauso.

                Außerdem müsste man bei fgets() auch jedesmal kontrollieren, ob das Zeilenende erreicht wurde, oder ob das Lesen vorher abgebrochen wurde wegen Erreichen der vorgegebenen Anzahl Bytes oder ob ein Fehler aufgetreten ist.

                PHP ist hier meiner Meinung nach sehr schlampig mit der Fehlerauswertung, indem es die Fehlercodes einfach verschluckt.

                Bei den ganzen Dateizugriffsfunktionen würde ich mir wünschen, entweder subsatantiierte Fehlernummern (auch "Erfolgsnummer") zu erhalten (NICHT Texte, deren Konsistenz in den unterschiedlichen Sprachversionen in Frage steht!), oder aber mich in keiner Weise darum kümmern zu müssen. Zweiteres ist aber wohl eine Utopie. So wie PHP das handhabt, ist es aber nicht Fisch und nicht Fleisch. Dabei wäre das ganz einfach ins Modell einzubauen. Unter der Verbindungskennung (Handle) könnte man doch entsprechende Funktionen anbieten, die Auskunft über die Zustände anbieten.

                feof($fh) ist doch schon eine davon.
                Eine zweite wäre "timeout($fh)", eine dritte "error_status($fh)" usw.
                Wobei error_status($fh,$mask) sogar ein (16-)Bit-Muster mit den unterschiedlichen Möglichkeiten prüfen könnte, sodass Fehlerabfragen auch gebündelt stattfinden könnten.

                Harzliche Grüße aus
                Sankt Andreasberg
                und Guten Rutsch

                Tom

                --
                Nur selber lernen macht schlau

                1. Hi,

                  würde ich mir wünschen, entweder subsatantiierte Fehlernummern [...] zu erhalten

                  ^^^^^
                  Du behandelst also Fehler gerne nach dem Motto "the devil may care" ...?

                  *SCNR*
                  ChrisB

                  1. Hello,

                    würde ich mir wünschen, entweder subsatantiierte Fehlernummern [...] zu erhalten
                                                          ^^^^^
                    Du behandelst also Fehler gerne nach dem Motto "the devil may care" ...?

                    Es wäre eher mit dem Teufel zugegengen, wenn diesmal kein Schreibfehler dringesteckt hätte.
                    Irgendwas macht den Firefox seit Tagen langsam...
                    Ich kann noch zusehen, wie die Zeichen in die Textarea purzeln, wenn ich sie schon seit drei Sekunden getippt habe. Ich habe diese Webdeveloper-Symbolleiste eingebunden, seitdem steht das Teil fast.

                    Ich glaube fast, da steckt eine Überraschung drin :-((

                    Harzliche Grüße aus
                    Sankt Andreasberg
                    und Guten Rutsch

                    Tom

                    --
                    Nur selber lernen macht schlau

        2. Hello,

          * EOF (end of file) is reached

          Das Ende der Datei wurde erreicht

          oder bei Eingabe von der Konsole wurde ^Z gefunden.

          * a packet becomes available (for network streams)

          Ein Paket wurde verfügbar, sprich: empfangen (trifft bei Netzwerkverkehr zu)

          Das ist sehr schwabbelig formuliert. Es soll vermutlich doch heißen, dass der Dateninhalt des aktuellen Paketes vollständig eingelesen wurde. Das Auslesen des nächsten wird dann also nicht automatisch begonnen. Es ist also ein blockorientiertes Lesen.

          Oder verstehe ich das falsch?

          Müsste man also mal wieder in den Source-Code gucken.

          Harzliche Grüße aus
          Sankt Andreasberg
          und Guten Rutsch

          Tom

          --
          Nur selber lernen macht schlau