Das Deutsche PHP Forum

Einklappen
Keine Ankündigung bisher.

Das Deutsche PHP Forum

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • socket_read laeuft in Endlosschleife

    Hallo community,

    ich hardere mittlerweile seit einigen Tagen mit einem Problem, das zwar durchaus in einigen Foren beschrieben, aber bisher nie mit einer funktionierenden Loesung beschrieben steht. Zudem sind die meisten Threads dazu alle einigen Jahre alt.

    Konkret geht es um die Funktion socket_read. In einem Programm habe ich bisher immer eine ueberschaubare Anzahl an Bytes ausgetauscht, sodass das Einlesen von 1024 Bytes $buf = socket_read($socket, 1024, PHP_BINARY_READ) immer ausreichend war. Jetzt hat sich das Anforderungsprofil jedoch veraendert, sodass eine beliebige Anzahl an Bytes eingelesen werden muss. Die natuerliche Loesung ist, socket_read in einer Schleife solange aufzurufen, bis der Buffer leer ist; wobei dies auch bereits die kritische Stelle ist, da PHP genau dies nicht zu erkennen scheint. Dies laesst sich sehr schnell verdeutlichen, wenn man jeweils nur eine Laenge von 10 oder 20 Bytes einliest.

    Hier sind die zwei exemplarischen Ansaetze, die ich im Netz zwar gefunden habe, aber die jedoch leider alle nicht funktionieren (aus Auskommentierte diente mir zu Debugzwecken):
    PHP-Code:
        /*
                $reply = "";
                do {
                    $recv = "";
                    $recv = @ socket_read($socket, '20');
                    if ($recv != "") {
                        $reply .= $recv;

                    }
                } while ($recv != "");
        */ 
    oder
    PHP-Code:
        while(($out=@socket_read($socket10PHP_NORMAL_READ)) !== FALSE) {

            
    // if ($out === FALSE) {
            //    continue;
            // }

            // $out = @socket_read($socket, 10);
            
    $foo .= $out;

            
    //if (empty($out)) {
            //    break;
            // }

            
    if ($i == 80)
                die(
    var_dump($foo2));

            
    // if (strlen($out) < 10)
            //    break;

            
    if (strlen($out) == 0) { break; }

            
    $i++;
        } 
    Das einzige, was das zweite Beispiel nicht in eine Endlosschleife verfallen laesst, ist, wenn ich pruefe, ob die Laenge des zuletzt eingelesenen Buffers kleiner als das Maximale (10 in diesem Fall) ist:
    PHP-Code:
    if (strlen($out) < 10)
      break; 
    Das ganze halte ich jedoch fuer keine stabile Loesung, da ja zufaellig auch genau 10 Bytes uebertragen werden koennten. Dann wuerde das Script erneut socket_read aufrufen und wieder in die Endlosschleife wandern.

    Die Hinweise hier PHP: socket_read - Manual haben leider auch nicht zielfuehrend weitergeholfen. Bei den obigen Scriptauszuegen wird die Endlosschleife immer erst dann unterbrochen, wenn der sendende Client beendet wird (CTRL+C).

    Einige User haben irgendwann einfach fsockopen() verwendet, als sie offensichtlich nicht weitergekommen sind. Das ganze geht in meinem Fall leider nicht, da es sich hier um einen Socket Server handelt, der eine beliebige Menge an Daten einlesen koennen muss.

    Ueber jegliche Ideen wuerde ich mich sehr freuen,
    dertechniker

  • #2
    soweit ich dich nun verstanden habe, würde ich sagen nimm socket_select. socket_select erkennt wenn Daten im socket zum lesen anliegen oder der socket zum schreiben bereit ist
    DevBlog|3D Online-Shopping|Xatrium

    Kommentar


    • #3
      Hallo tiberius,

      vielen Dank fuer das passende Stichwort - socket_select hat genau die gewuenschten Dienste erfuellt. Fuer alle, die noch auf das gleiche Problem stossen werden, hier die passenden Zeilen.

      PHP-Code:
          $read = array($socket);
          
      $write = array($socket);

          
      $data '';
          while((
      $buf=@socket_read($socket1024PHP_NORMAL_READ))) {

              
      $data .= $buf;

              if (
      $ret socket_select($read$write$except NULLNULL) < 2)
                  break;

          } 
      Noch als Anmerkung: $write durfte in meinem Fall nicht NULL sein, ansonsten lief es erneut in die Endlosschleife.

      Vielen Dank noch mal,
      dertechniker

      Kommentar


      • #4
        In den letzten Tagen ist mir noch ein weiteres - wenn auch seltsames - Phaenomen aufgefallen. Und zwar ist es bei mir vorgekommen, dass vom Server an einer Stelle via socket_write diverse Zeilen hintereinander geschickt werden, ohne dass dieser zwischendurch einliest (der Client schickt in dieser Zeit natuerlich auch nichts). Dabei habe ich beobachtet, dass der Server zwar alles richtig verschickt, aber beim Client immer wieder unterschiedliche Zeilen nicht ankommen, also als ob sie gar nicht versendet worden waeren.

        Obiges nun schematisch dargestellt (S = Server, C = Client).

        S -> Textzeile 1 -> C
        S -> Textzeile ... -> C
        S -> Textzeile n -> C

        Erst als ich mein internes Protokoll so umgebaut hatte, dass jedes socket_write des Servers mit einer kurzen Empfangsbestaetigung beantwortet wurde (socket_write and socket_read jeweils im Wechsel), hat alles so geklappt wie es sollte. Schematisch:

        S -> Textzeile 1 -> C
        C -> Erhalten: Textzeile 1 -> S
        S -> Textzeile ... -> C
        C -> Erhalten: Textzeile ... -> S
        S -> Textzeile n -> C
        C -> Erhalten: Textzeile n -> S

        Vielleicht ist das ja fuer andere spaeter noch hilfreich.

        Gruesse,
        dertechniker

        Kommentar


        • #5
          würde sagen dass da bei dir was nicht richtig läuft, wie hast du socket read/write denn implementiert?
          DevBlog|3D Online-Shopping|Xatrium

          Kommentar

          Lädt...
          X