PHP socket_set_timeout() Funktion: Alles, was Sie wissen müssen
Erfahren Sie, wie socket_set_timeout() in PHP Timeouts für Streams setzt, häufige Fallstricke vermeidet und wie Sie Timeouts zuverlässig erkennen.
Wenn Ihr Skript von einer Netzwerkverbindung liest, kann ein langsamer oder ausgefallener Server PHP auf unbestimmte Zeit blockieren, einen Worker belegen und Benutzer frustrieren. Die Funktion socket_set_timeout() setzt eine Frist für Lese- und Schreiboperationen, sodass eine blockierte Verbindung schnell scheitert, anstatt zu hängen. Dieser Artikel erklärt genau, was sie steuert, die häufigsten Fallstricke und wie Sie einen Timeout erkennen, wenn er auftritt.
Was die Funktion socket_set_timeout() tut
socket_set_timeout() legt den Timeout für I/O-Operationen fest — fread(), fgets(), fwrite() usw. — auf einem Stream, der mit fsockopen() oder pfsockopen() geöffnet wurde. Wenn ein Lese- oder Schreibvorgang nicht innerhalb der Frist abgeschlossen wird, gibt die Operation frühzeitig zurück und der Stream wird als timed out markiert.
Zwei Dinge tut sie nicht:
- Sie beeinflusst nicht den Verbindungs-Timeout. Das ist das fünfte Argument von
fsockopen($host, $port, $errno, $errstr, $connectTimeout).socket_set_timeout()regelt nur die Datenübertragung, nachdem die Verbindung hergestellt ist. - Sie lässt den Aufruf nicht laut scheitern. Ein Lesevorgang, der einen Timeout erreicht, gibt die bisher empfangenen Daten zurück (oft ein leerer string) und setzt ein Flag — Sie müssen dieses Flag selbst mit
stream_get_meta_data()prüfen.
Namens-Falle: Trotz des
socket_-Präfixes gehört diese Funktion zur Streams-Familie und nicht zur Sockets-Erweiterung. Sie funktioniert mit Ressourcen ausfsockopen(), niemals mit einer Ressource aussocket_create(). Seit PHP 8.0 ist sie ein veralteter Alias vonstream_set_timeout()— bevorzugen Sie diesen Namen in neuem Code.
Syntax
socket_set_timeout(resource $stream, int $seconds, int $microseconds = 0): bool| Parameter | Beschreibung |
|---|---|
$stream | Eine offene Stream-Ressource, die von fsockopen() oder pfsockopen() zurückgegeben wird. |
$seconds | Der Timeout in ganzen Sekunden. |
$microseconds | Zusätzliche Zeit in Mikrosekunden (optional, Standard 0). |
Die Funktion gibt true bei Erfolg und false bei Fehler zurück (zum Beispiel wenn $stream keine gültige Stream-Ressource ist).
Ein funktionierendes Beispiel
Öffnen Sie eine Verbindung, setzen Sie einen 5-Sekunden-Lese-Timeout und prüfen Sie dann, ob ein Lesevorgang einen Timeout hatte:
<?php
// Open a TCP connection to a web server.
$stream = fsockopen("www.example.com", 80, $errno, $errstr, 10);
if (!$stream) {
echo "Connection failed: $errstr ($errno)\n";
exit;
}
// Fail any single read/write that stalls for more than 5 seconds.
socket_set_timeout($stream, 5);
// Send a minimal HTTP request.
fwrite($stream, "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n");
// Read the first line of the response.
$line = fgets($stream, 1024);
// Check whether that read hit the timeout.
$info = stream_get_meta_data($stream);
if ($info['timed_out']) {
echo "Read timed out — the server was too slow.\n";
} else {
echo "First response line: " . trim($line) . "\n";
}
fclose($stream);Der Schlüssel ist der stream_get_meta_data()-Aufruf: Sein Element timed_out ist der einzige zuverlässige Weg, einen echten Timeout von einer Verbindung zu unterscheiden, die einfach geschlossen wurde.
Lesen in einer Schleife
Wenn Sie eine vollständige Antwort lesen, prüfen Sie bei jeder Iteration timed_out, damit ein Stillstand mitten in der Übertragung Ihre Daten nicht stillschweigend abschneidet:
<?php
$stream = fsockopen("www.example.com", 80, $errno, $errstr, 10);
socket_set_timeout($stream, 5);
fwrite($stream, "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n");
$body = "";
while (!feof($stream)) {
$chunk = fgets($stream, 4096);
$info = stream_get_meta_data($stream);
if ($info['timed_out']) {
echo "Stalled before the response finished.\n";
break;
}
$body .= $chunk;
}
fclose($stream);
echo "Received " . strlen($body) . " bytes.\n";Häufige Fallstricke
- Falscher Ressourcentyp. Eine
socket_create()-Ressource zu übergeben bewirkt nichts Nützliches — verwenden Siestream_set_timeout()mitsocket_create()-Sockets odersocket_set_option()fürSO_RCVTIMEO/SO_SNDTIMEO. - Verbindungs- und Lese-Timeout verwechseln. Ein langer
fsockopen()-Verbindungs-Timeout schützt Sie nicht vor einer langsamen Antwort; Sie benötigen beides. - Vergessen,
timed_outzu prüfen. Ohne diese Prüfung sieht ein Lese-Timeout genauso aus wie ein normales Ende des Streams, was zu stillschweigend abgeschnittenen Daten führt.
Verwandte Funktionen
fsockopen()— öffnet den Stream, auf dem diese Funktion operiert.stream_get_meta_data()über socket_get_status() — liest dastimed_out-Flag.socket_set_blocking()— wechselt einen Stream zwischen Blocking- und Non-Blocking-Modus.fgets()undfwrite()— die I/O-Aufrufe, auf die der Timeout angewendet wird.
Fazit
socket_set_timeout() verhindert, dass langsame Netzwerk-Lese- und Schreibvorgänge Ihr PHP-Skript blockieren. Denken Sie daran, dass sie auf fsockopen()-Streams (nicht auf die Sockets-Erweiterung) wirkt, I/O statt der Verbindung regelt und dass Sie das timed_out-Flag von stream_get_meta_data() prüfen müssen, um zu wissen, ob tatsächlich ein Timeout aufgetreten ist. Verwenden Sie in neuem Code den modernen Namen stream_set_timeout().