PHP pfsockopen()-Funktion: Alles, was Sie wissen müssen
Erfahren Sie, wie die PHP-Funktion pfsockopen() persistente Socket-Verbindungen öffnet, welche Parameter sie hat und welche moderne Alternative es gibt.
Die Funktion pfsockopen() öffnet eine persistente Internet- oder Unix-Domain-Socket-Verbindung. „Persistent" bedeutet, dass der zugrunde liegende Socket offen bleibt, nachdem das Skript beendet wurde, und von späteren Anfragen wiederverwendet wird, die sich mit demselben Host und Port verbinden — dadurch entfallen die Kosten für das Öffnen einer neuen Verbindung (DNS-Lookup, TCP-Handshake) bei jeder Anfrage.
Wichtig:
pfsockopen()wurde in PHP 8.1 als veraltet markiert und in PHP 8.2 entfernt, sodass es in modernem PHP nicht mehr verfügbar ist. Dieses Kapitel dokumentiert das historische Verhalten und zeigt, was stattdessen verwendet werden sollte. Wenn Sie PHP 8.2+ verwenden, springen Sie zu Moderne Alternative.
Dieses Kapitel behandelt, was pfsockopen() leistete, seine Syntax und Parameter, ein ausgearbeitetes HTTP-Beispiel, den Unterschied zwischen persistenten und nicht-persistenten Sockets, häufige Fallstricke und den empfohlenen Ersatz.
Was ist die pfsockopen()-Funktion?
pfsockopen() („persistentes fsockopen") ist der persistente Zwilling von fsockopen(). Beide öffnen einen Low-Level-Socket und geben einen Stream zurück, aus dem Sie lesen und in den Sie mit den üblichen Dateifunktionen schreiben können. Der einzige Unterschied: Eine mit fsockopen() geöffnete Verbindung wird am Ende der Anfrage geschlossen, während eine mit pfsockopen() geöffnete Verbindung vom PHP-Prozess gepoolted und bei nachfolgenden Anfragen an dasselbe Ziel wiederverwendet wird.
Dies machte sie nützlich in langlebigen Setups (FPM/mod_php-Worker), bei denen dasselbe Skript wiederholt mit demselben Backend kommunizierte — beispielsweise ein Memcached-Node oder ein benutzerdefinierter TCP-Dienst — und der Handshake-Overhead pro Anfrage vermieden werden sollte.
Verwendung der pfsockopen()-Funktion
Hier ist die Syntax der Funktion:
Die PHP-Syntax der pfsockopen()-Funktion
pfsockopen($hostname, $port, &$errno, &$errstr, $timeout);Die Funktion nimmt fünf Parameter entgegen:
$hostname: Der Hostname oder die IP-Adresse des Servers, mit dem eine Verbindung hergestellt werden soll.$port: Die Portnummer, zu der eine Verbindung hergestellt werden soll.$errno: Eine per Referenz übergebene Variable, die bei einem Fehler auf die Fehlernummer gesetzt wird.$errstr: Eine per Referenz übergebene Variable, die bei einem Fehler auf die Fehlermeldung gesetzt wird.$timeout: Der Timeout-Zeitraum in Sekunden.
Nur $hostname und $port sind erforderlich; $errno, $errstr und $timeout sind optional, aber es lohnt sich fast immer, sie zu übergeben, damit Sie Fehler diagnostizieren können.
Rückgabewert: Gibt bei Erfolg einen Stream/eine Ressource zurück oder false bei einem Fehler.
Hier ist ein Beispiel, wie die Funktion pfsockopen() verwendet werden kann, um eine persistente Socket-Verbindung herzustellen, Fehler zu behandeln und Daten auszutauschen:
Verwendung der pfsockopen()-Funktion
<?php
$hostname = "example.com";
$port = 80;
$errno = 0;
$errstr = "";
$timeout = 30;
$socket = pfsockopen($hostname, $port, $errno, $errstr, $timeout);
if ($socket === false) {
echo "Connection failed: $errno - $errstr";
} else {
fwrite($socket, "GET / HTTP/1.1\r\nHost: $hostname\r\n\r\n");
$response = fread($socket, 2048);
echo $response;
fclose($socket);
}
?>Hier öffnen wir eine Verbindung zu example.com auf Port 80 mit einem 30-Sekunden-Timeout. Bei einem Fehler landen die Fehlernummer und -meldung in $errno/$errstr. Nach dem Verbindungsaufbau senden wir eine rohe HTTP-Anfrage mit fwrite(), lesen die Antwort mit fread() und schließen das Handle mit fclose().
Ein zurückgegebener Stream verhält sich wie jeder andere PHP-Stream, sodass dieselben I/O-Funktionen, die Sie mit fopen() verwenden, auch hier funktionieren.
Persistente vs. nicht-persistente Sockets
Die folgende Tabelle zeigt, wann das jeweilige Verhalten wichtig ist:
| Aspekt | fsockopen() | pfsockopen() |
|---|---|---|
| Verbindungslebensdauer | Wird am Ende der Anfrage geschlossen | Gepoolted und über Anfragen hinweg wiederverwendet |
| Kosten der ersten Anfrage | Vollständiger Handshake bei jeder Anfrage | Vollständiger Handshake nur bei der ersten Anfrage |
| Am besten für | Einmalige oder kurze Skripte | Wiederholte Aufrufe an dasselbe Backend in langlebigen Workern |
Persistenz hilft nur dann, wenn derselbe Prozess viele Anfragen an denselben Host/Port bedient — typischerweise PHP-FPM oder mod_php. In CLI-Skripten, die sofort beendet werden, gibt es nichts wiederzuverwenden, sodass pfsockopen() wie fsockopen() verhält.
Häufige Fallstricke
fclose()schließt die Verbindung nicht wirklich. Das Aufrufen vonfclose()bei einem persistenten Socket gibt diesen nur an den Pool zurück. Das ist der Sinn der Sache — aber das bedeutet, dass eine halb defekte Verbindung an die nächste Anfrage weitergegeben werden kann. Validieren Sie die Verbindung immer (oder senden Sie einen leichten Ping), bevor Sie sich darauf verlassen.- Kein Multiplexing. Jeder PHP-Worker verwaltet seinen eigenen Pool, sodass die Anzahl der persistenten Sockets mit Ihrer Worker-Anzahl wächst. Ein stark ausgelasteter Server kann das Verbindungslimit des Backends erschöpfen.
- Zustandslecks. Da der Socket zwischen Anfragen bestehen bleibt, können übrig gebliebene gepufferte Daten oder ein Zwischen-Protokoll-Zustand einer früheren Anfrage die nächste korrumpieren. Persistente Sockets eignen sich am besten für einfache, zustandslose Request/Response-Protokolle.
- Entfernt in PHP 8.2. Code, der
pfsockopen()noch aufruft, wird unter PHP 8.2+ einen fatalenCall to undefined function-Fehler auslösen.
Moderne Alternative
Unter PHP 8.2+ verwenden Sie stream_socket_client() mit dem Flag STREAM_CLIENT_PERSISTENT. Es ist flexibler (unterstützt tcp://-, tls://- und unix://-Transporte sowie Stream-Kontexte) und ist die aktiv gepflegte API:
<?php
$socket = stream_socket_client(
"tcp://example.com:80",
$errno,
$errstr,
30,
STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT
);
if ($socket === false) {
echo "Connection failed: $errno - $errstr";
} else {
fwrite($socket, "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
echo fread($socket, 2048);
fclose($socket);
}
?>Für alltägliche HTTP-Arbeit ist ein übergeordneter Client wie cURL oder Guzzle in der Regel die bessere Wahl — greifen Sie nur dann auf rohe Sockets zurück, wenn Sie ein benutzerdefiniertes Protokoll benötigen.
Fazit
pfsockopen() erstellte eine persistente, wiederverwendbare Socket-Verbindung — praktisch für langlebige PHP-Worker, die wiederholt dasselbe Backend kontaktierten. Das entscheidende Merkmal war, dass fclose() den Socket in einen Pool zurückgab, anstatt ihn zu schließen. Da die Funktion in PHP 8.2 entfernt wurde, sollte neuer Code stream_socket_client() mit STREAM_CLIENT_PERSISTENT verwenden. Um verwandte Stream-I/O zu erkunden, lesen Sie fsockopen(), fwrite() und fread().