fget mit unbekannt Länge einlesen

3 views
Skip to first unread message

Timo S.

unread,
Oct 28, 2020, 4:18:02 AM10/28/20
to
Guten Morgen,

ich sitze gerade an einer Funktion mit fsockopen,
die von eine Liste mit Fehlern von einem Serverport abfragt.

Dabei steht jeder Fehler in einer eigenen Zeile und die Liste
der Fehler ist mal leer und auch mal schnell mehrere hundert Zeilen groß.

Wie bringe ich PHP bzw. fgets dazu, alles einschließlich der letzten
Zeile in die Variable $ErrorList_Response zu schreiben.
Aktuell wird nur die erste Zeile in $ErrorList_Response gespeichert.

Meine Abfrage der Zeile sieht wie folgt aus:

fputs( $smtpConnect, "LIST" . $newLine );
$ErrorList_Response .= fgets( $smtpConnect, 1024 );

Hat jemand eine Idee und einen Lösungsansatz für mich?

Vielen Dank.

Gruß
Timo

Karl Pflästerer

unread,
Oct 28, 2020, 10:17:30 AM10/28/20
to
Hast du https://www.php.net/fsockopen gelesen? In der while Schleife
liest du alle Zeilen ein

KP

Timo

unread,
Oct 28, 2020, 12:11:03 PM10/28/20
to
Am 28.10.2020 um 15:17 schrieb Karl Pflästerer:
> Hast du https://www.php.net/fsockopen gelesen? In der while Schleife
> liest du alle Zeilen ein
>
> KP
>

Wenn ich die Abfrage in eine Whileschleife lege,
wird das ganze zur Endlosschleife und bricht ab.

Das Script sieht im gesamten wie folgt aus:

$DataServer = "lhennen01.intra.xxxxxxxxxxxx.xx";
$DataPort = "1020";
$timeout = "20";

$username = "snadmin";
$password = "*******";
$newLine = "\r\n";

$DatapConnect = fsockopen( $DataServer, $DataPort, $errno, $errstr,
$timeout );
$DataResponse .= fgets( $DatapConnect, 515 );
if ( empty( $DatapConnect ) )
{
$output = "Failed to connect: $DataResponse";
return $output;
}

# StallNet Benutzerdaten senden
fputs( $DatapConnect, "AUTHUSER " . $username . $newLine );
$DataResponse .= fgets( $DatapConnect, 256 );
fputs( $DatapConnect, "AUTHPASS " . $password . $newLine );
$DataResponse .= fgets( $DatapConnect, 1024 );

# In die Serviceebene wechseln
fputs( $DatapConnect, "ENABLE SERVICEMODE" . $newLine );
$DataResponse .= fgets( $DatapConnect, 1024 );

# Fehlerliste abfragen
fputs( $DatapConnect, "READ ERRORLIST" . $newLine );
while (!feof($DatapConnect)) {
echo fgets($DatapConnect, 1024);
}

# Fehlerspeicher leeren
#fputs( $DatapConnect, "CLEAR ERRORLIST" . $newLine );
#$DataResponse .= fgets( $DatapConnect, 256);

# Aus der Serviceebene wechseln
fputs( $DatapConnect, "DISABLE SERVICEMODE" . $newLine );
$DataResponse .= fgets( $DatapConnect, 256);

# Aus System abmelden
fputs( $DatapConnect, "QUIT" . $newLine );
$DataResponse .= fgets( $DatapConnect, 256 );

# Verbindung schliessen
fclose( $DatapConnect );



Das ursprüngliche Script, von dem ich dieses abgeleitet habe,
wird für Verbindungen zu einem SMTP genutzt.

Der Zweck für den ich das Script nutzen möchte,
ist von der Befehlübermittlung und auch der Abfrage ähnlich wie SMTP.

Ich habe es auch schon mit einer for-Schleife versucht, dabei ist es
jedoch so, dass dies funktioniert, solange man weniger Zeilen abfragt,
als die übertragene Liste hat und das Script ist innerhalb einer Sekunde
durch.

Wenn man bei der for-Schleife jedoch dann mehr Zeilen eingibt bzw. die
Schleife mindestens einmal zu oft läuft, bekommt man die Fehlermeldung,
dass bei der Zeile oberhalb der if-Abfrage

$DataResponse .= fgets( $DatapConnect, 515 );

den Fehler, dass $DataResponse nicht definiert ist und das Script bricht
dann irgendwann ab, obwohl nichteinmal alle Zeilen eingelesen wurde.
Gleiches gilt für die Verwendung mit while-Schleife wie oben im Script.

Leider kann man auf dem System nicht abfragen, wie viele Fehler / Zeilen
in der Liste sind.

Gruß

Timo

Arno Welzel

unread,
Oct 28, 2020, 4:11:49 PM10/28/20
to
Timo S.:
Generell wäre socket_read() dafür sinnvoller.

Ganz simpel:

$ErrorList_Response .= socket_read($smtpConnect, 1024);

Wobei 1024 ja auch zu wenig sein könnte:

$ErrorList_Response .= socket_read($smtpConnect, 16384);

Die ausführlichere Variante:

$done = false;
$timeOut = 10;
$data = '';
while (!$done && $timeOut > 0) {
$listRead = [$smtpConnect];
$listWrite = null;
$listExcept = null;
$socketRead = @socket_select($listRead, $listWrite, $listExcept, 1);
if($socketRead) {
$runtime = 0;
$buffer = socket_read($smtpConnect, 8192);
if (strlen($buffer) > 0) {
$data .= $buf;
} else {
$done = true;
}
} else {
$timeOut--;
}
}

Die Idee dabei:

Man fragt mit socket_select() ab, ob am Socket noch etwas zu lesen und
vermeidet so einen Hänger, wenn der angesprochene Server nichts
zurückschickt.

Wenn etwas bereitsteht, liest dann bis zu 8 KB ein. Wenn es nichts mehr
zu lesen gibt, gibt man dem Sender noch maximal 10 Sekunden Zeit und
bricht dann ab - wobei man jeweils einmal pro Sekunde prüft.


--
Arno Welzel
https://arnowelzel.de
Reply all
Reply to author
Forward
0 new messages