Función PHP pfsockopen(): Todo lo que necesitas saber
Aprende cómo pfsockopen() abre conexiones de socket persistentes en PHP, su sintaxis, parámetros y la alternativa moderna con stream_socket_client().
La función pfsockopen() abre una conexión de socket de dominio Internet o Unix persistente. "Persistente" significa que el socket subyacente permanece abierto después de que el script finaliza y es reutilizado por solicitudes posteriores que se conectan al mismo host y puerto, ahorrando el costo de abrir una nueva conexión (búsqueda DNS, handshake TCP) cada vez.
Importante:
pfsockopen()fue deprecada en PHP 8.1 y eliminada en PHP 8.2, por lo que no está disponible en PHP moderno. Este capítulo documenta su comportamiento histórico y muestra qué usar en su lugar. Si estás en PHP 8.2+, salta a Alternativa moderna.
Este capítulo cubre qué hacía pfsockopen(), su sintaxis y parámetros, un ejemplo HTTP práctico, la diferencia entre sockets persistentes y no persistentes, errores comunes y el reemplazo recomendado.
¿Qué es la función pfsockopen()?
pfsockopen() ("persistent fsockopen") es el gemelo persistente de fsockopen(). Ambas abren un socket de bajo nivel y devuelven un stream que puedes leer y escribir con las funciones de archivo habituales. La única diferencia: una conexión abierta con fsockopen() se cierra al final de la solicitud, mientras que una abierta con pfsockopen() es agrupada por el proceso PHP y reutilizada en solicitudes posteriores al mismo destino.
Esto la hacía útil en configuraciones de larga duración (workers FPM/mod_php) donde el mismo script hablaba repetidamente con el mismo backend — por ejemplo un nodo memcached o un servicio TCP personalizado — y valía la pena evitar el overhead del handshake por solicitud.
Cómo usar la función pfsockopen()
Esta es la sintaxis de la función:
La sintaxis PHP de la función pfsockopen()
pfsockopen($hostname, $port, &$errno, &$errstr, $timeout);La función toma cinco parámetros:
$hostname: El nombre de host o dirección IP del servidor al que conectarse.$port: El número de puerto al que conectarse.$errno: Una variable pasada por referencia que se establecerá con el número de error si ocurre uno.$errstr: Una variable pasada por referencia que se establecerá con el mensaje de error si ocurre uno.$timeout: El período de tiempo de espera en segundos.
Solo $hostname y $port son obligatorios; $errno, $errstr y $timeout son opcionales pero casi siempre vale la pena pasarlos para poder diagnosticar fallos.
Valor de retorno: Devuelve un stream/recurso en caso de éxito, o false en caso de fallo.
A continuación se muestra un ejemplo de cómo usar la función pfsockopen() para crear una conexión de socket persistente, manejar errores e intercambiar datos:
¿Cómo usar la función pfsockopen()?
<?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);
}
?>Aquí abrimos una conexión a example.com en el puerto 80 con un tiempo de espera de 30 segundos. En caso de fallo, el número y mensaje de error quedan en $errno/$errstr. Una vez conectados, enviamos una solicitud HTTP sin procesar con fwrite(), leemos la respuesta con fread() y cerramos el manejador con fclose().
Un stream devuelto se comporta como cualquier otro stream PHP, por lo que las mismas funciones de E/S que usas con fopen() también funcionan aquí.
Sockets persistentes vs. no persistentes
La siguiente tabla muestra cuándo importa cada comportamiento:
| Aspecto | fsockopen() | pfsockopen() |
|---|---|---|
| Duración de la conexión | Cerrada al final de la solicitud | Agrupada y reutilizada entre solicitudes |
| Costo de la primera solicitud | Handshake completo cada vez | Handshake completo solo en la primera solicitud |
| Ideal para | Scripts únicos o de corta duración | Llamadas repetidas al mismo backend en workers de larga duración |
La persistencia solo ayuda cuando el mismo proceso atiende muchas solicitudes al mismo host/puerto — típicamente PHP-FPM o mod_php. En scripts CLI que salen inmediatamente, no hay nada que reutilizar, por lo que pfsockopen() se comporta como fsockopen().
Errores comunes
fclose()no lo cierra realmente. Llamar afclose()en un socket persistente solo lo devuelve al grupo. Ese es el objetivo — pero significa que una conexión medio rota puede pasarse a la siguiente solicitud. Siempre valida la conexión (o envía un ping ligero) antes de depender de ella.- Sin multiplexación. Cada worker PHP mantiene su propio grupo, por lo que el número de sockets persistentes crece con la cantidad de workers. Un servidor ocupado puede agotar el límite de conexiones del backend.
- Filtraciones de estado. Como el socket sobrevive entre solicitudes, datos almacenados en búfer o un estado de protocolo incompleto de una solicitud anterior pueden corromper la siguiente. Los sockets persistentes son más adecuados para protocolos simples de solicitud/respuesta sin estado.
- Eliminada en PHP 8.2. El código que aún llama a
pfsockopen()lanzará un error fatalCall to undefined functionen PHP 8.2+.
Alternativa moderna
En PHP 8.2+, usa stream_socket_client() con el indicador STREAM_CLIENT_PERSISTENT. Es más flexible (admite transportes tcp://, tls:// y unix:// y contextos de stream) y es la API mantenida activamente:
<?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);
}
?>Para el trabajo HTTP cotidiano, un cliente de nivel superior como cURL o Guzzle suele ser la mejor opción — usa sockets sin procesar solo cuando necesites un protocolo personalizado.
Conclusión
pfsockopen() creaba una conexión de socket persistente y reutilizable — útil para workers PHP de larga duración que contactaban repetidamente el mismo backend. Su característica clave era que fclose() devolvía el socket a un grupo en lugar de cerrarlo. Dado que la función fue eliminada en PHP 8.2, el nuevo código debe usar stream_socket_client() con STREAM_CLIENT_PERSISTENT. Para explorar E/S de stream relacionada, consulta fsockopen(), fwrite() y fread().