Signatur
Beschreibung
pfsockopen() verhält sich genau wie fsockopen(), mit dem wesentlichen Unterschied, dass die geöffnete Verbindung persistent ist: Sie wird nach dem Ende des PHP-Skripts nicht automatisch geschlossen, sondern bleibt im Prozess-Pool (z. B. Apache-Worker) erhalten und kann vom nächsten Request wiederverwendet werden. Das spart den Overhead des erneuten Verbindungsaufbaus, besonders bei häufig genutzten TCP-Verbindungen.
Wie bei fsockopen() wird ein Stream-Resource-Handle zurückgegeben, das mit den üblichen Datei-Funktionen wie fgets(), fwrite(), feof() usw. genutzt werden kann. Der Parameter hostname kann eine IPv4/IPv6-Adresse, ein Hostname oder ein Unix-Socket-Pfad sein (z. B. unix:///tmp/my.sock). Transportprotokolle wie ssl:// oder tls:// werden ebenfalls unterstützt.
Die Persistenz funktioniert nur bei Webserver-SAPIs mit dauerhaft laufenden Prozessen (z. B. Apache mod_php). Beim CLI-SAPI oder FPM mit Process-Recycling bietet pfsockopen() kaum Vorteile gegenüber fsockopen(). Es ist wichtig zu beachten, dass persistente Verbindungen nicht explizit mit fclose() geschlossen werden sollten, da dies die Verbindung aus dem Pool entfernt.
Fehlerdiagnose erfolgt über die Referenzparameter $errno und $errstr: Bei einem Verbindungsfehler enthält $errno den System-Fehlercode und $errstr eine lesbare Fehlermeldung.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $hostname Pflicht | string | Hostname, IP-Adresse oder Socket-Pfad. Unterstützt Transport-Wrapper wie ssl://, tls:// oder unix://. |
|
| $port | int | -1 | Port-Nummer für TCP/UDP-Verbindungen. Bei Unix-Domain-Sockets auf -1 setzen oder weglassen. |
| $errno | int | null | Wird per Referenz übergeben. Nach einem Fehler enthält diese Variable den System-Fehlercode. Ist der Wert 0, hat die Verbindung grundsätzlich funktioniert, aber der Fehler liegt auf einer höheren Ebene. |
| $errstr | string | null | Wird per Referenz übergeben. Enthält nach einem Fehler eine menschenlesbare Fehlermeldung. |
| $timeout | float | ini_get('default_socket_timeout') | Verbindungs-Timeout in Sekunden. Standardmäßig wird default_socket_timeout aus der php.ini verwendet. |
Rückgabewert
fgets() oder fwrite() verwendet werden kann. Bei einem Fehler wird false zurückgegeben und $errno/$errstr werden gesetzt.Beispiele
Persistente HTTP-Verbindung zu einem Webserver
<?php
$errno = 0;
$errstr = '';
$fp = pfsockopen('www.example.com', 80, $errno, $errstr, 5.0);
if ($fp === false) {
echo "Verbindungsfehler [{$errno}]: {$errstr}\n";
exit(1);
}
// HTTP-GET-Anfrage senden
fwrite($fp, "GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: Close\r\n\r\n");
// Antwort lesen
$response = '';
while (!feof($fp)) {
$response .= fgets($fp, 1024);
}
// Bei persistenten Verbindungen NICHT fclose() aufrufen,
// damit die Verbindung im Pool bleibt.
// fclose($fp); // <-- absichtlich weggelassen
echo substr($response, 0, 200);
?>
Verbindung zu einem SSL-gesicherten Server
<?php
$errno = 0;
$errstr = '';
// SSL-Verbindung auf Port 443
$fp = pfsockopen('ssl://www.example.com', 443, $errno, $errstr, 10.0);
if ($fp === false) {
echo "SSL-Verbindung fehlgeschlagen [{$errno}]: {$errstr}\n";
exit(1);
}
fwrite($fp, "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: Close\r\n\r\n");
$headers = '';
while (!feof($fp)) {
$line = fgets($fp, 512);
if ($line === "\r\n") {
break; // Ende der HTTP-Header
}
$headers .= $line;
}
echo $headers;
?>
// Wichtig · Fallstricke
Vorsicht mit persistenten Verbindungen: Da die Verbindung im Prozess-Pool erhalten bleibt, können Zustandsprobleme auftreten, wenn ein vorheriges Skript die Verbindung in einem undefinierten Zustand hinterlassen hat (z. B. halb empfangene Daten). Es empfiehlt sich, das Protokoll so zu gestalten, dass der Verbindungszustand nach jeder Nutzung klar definiert ist.
Kein fclose() bei persistenten Verbindungen: Das Aufrufen von fclose() auf einem persistenten Socket schließt die Verbindung tatsächlich und entfernt sie aus dem Pool. Nur wenn die Verbindung bewusst beendet werden soll, ist fclose() angebracht.
Sicherheitshinweis: Bei der Nutzung von ssl:// oder tls:// sollte die Peer-Zertifikatsprüfung via Stream-Kontext (stream_context_create()) aktiviert und konfiguriert werden, um Man-in-the-Middle-Angriffe zu verhindern.
PHP-FPM und CLI: Unter PHP-FPM mit kurzlebigen Prozessen oder beim CLI-Einsatz bringt pfsockopen() gegenüber fsockopen() keinen nennenswerten Vorteil, da kein langlebiger Prozess-Pool vorhanden ist.