fsockopen / pfsockopen în PHP

Socket-uri PHP 4+

Deschide o conexiune TCP (sau UDP, SSL) către un server și o returnează ca stream, pentru fwrite și fgets.

Sintaxă
fsockopen(string $hostname, int $port = -1, &$error_code = null, &$error_message = null, ?float $timeout = null)

Ce face fsockopen / pfsockopen

fsockopen se conectează la un server, după nume sau IP și port, și returnează un stream obișnuit. Pe el scrii cu fwrite și citești cu fgets sau fread, ca într-un fișier. Este cel mai simplu mod de a vorbi direct cu un server SMTP, Redis, un port de imprimantă sau un serviciu propriu.

Implicit, conexiunea este TCP. Pentru alt transport, pune-l în fața numelui: udp://, ssl://, tls://. La eșec, funcția returnează false, afișează un avertisment și pune codul și mesajul erorii în $error_code și $error_message.

pfsockopen are aceiași parametri, dar conexiunea este persistentă: nu se închide la finalul scriptului, ci este refolosită de cererile următoare servite de același proces PHP-FPM.

Parametri

Parametru Descriere
$hostname Numele sau IP-ul serverului, opțional cu transport în față (ssl://smtp.exemplu.ro).
$port Portul serverului.
$error_code Opțional. Variabilă în care se pune codul erorii de sistem.
$error_message Opțional. Variabilă în care se pune mesajul erorii.
$timeout Opțional. Secundele de așteptare pentru conectare. Implicit default_socket_timeout (60).

Ce returnează

Un stream conectat sau false dacă nu s-a putut conecta.

Exemple

Exemplul 1: Conversație cu un server local

Pornim în același script un server pe un port liber (portul 0 cere sistemului să aleagă unul). fsockopen se conectează la el, iar cele două capete își trimit câte o linie.

<?php
$server = stream_socket_server("tcp://127.0.0.1:0");
$port = (int) explode(":", stream_socket_get_name($server, false))[1];

$client = fsockopen("127.0.0.1", $port, $cod, $mesaj, 2);
$conexiune = stream_socket_accept($server);

fwrite($client, "Salut, server!\n");
echo "Serverul a primit: " . fgets($conexiune);

fwrite($conexiune, "Salut, Ana!\n");
echo "Clientul a primit: " . fgets($client);

Rezultat

Serverul a primit: Salut, server!
Clientul a primit: Salut, Ana!

Exemplul 2: O cerere HTTP scrisă de mână

<?php
$s = fsockopen("www.exemplu.ro", 80, $cod, $mesaj, 5);

fwrite($s, "HEAD / HTTP/1.1\r\nHost: www.exemplu.ro\r\nConnection: close\r\n\r\n");
echo fgets($s);
fclose($s);

Rezultat posibil (depinde de server)

HTTP/1.1 200 OK

Exemplul 3: Tratarea erorii de conectare

Pe portul 1 nu ascultă nimic. @ ascunde avertismentul, iar mesajul vine în $mesaj. Codul din $cod depinde de sistem (111 pe Linux, 61 pe macOS), de aceea afișăm doar mesajul.

<?php
$s = @fsockopen("127.0.0.1", 1, $cod, $mesaj, 2);

if ($s === false) {
    echo "Serviciul nu răspunde: $mesaj";
}

Rezultat

Serviciul nu răspunde: Connection refused

Greșeli frecvente

  • Nu dai $timeout. Dacă serverul nu răspunde, scriptul așteaptă 60 de secunde. Pune 2-5 secunde pentru servicii din aceeași rețea.
  • Scrii "https://www.exemplu.ro" ca nume. fsockopen nu înțelege adrese web; pentru HTTPS folosește ssl://www.exemplu.ro și portul 443, sau mai simplu file_get_contents ori cURL.
  • Citești cu fgets până la feof o conexiune HTTP fără Connection: close. Serverul ține conexiunea deschisă și bucla așteaptă până la timeout.

Comenzi înrudite

  • stream_socket_client: Deschide o conexiune către un server dată ca adresă completă (tcp://, udp://, tls://, unix://) și o returnează ca stream.
  • stream_set_timeout: Stabilește cât timp așteaptă o citire de pe un socket înainte să renunțe.
  • fgets: Citește o linie dintr-un fișier deschis cu fopen.
  • fwrite / fputs: Scrie un text într-un fișier deschis cu fopen. fputs este același lucru, cu alt nume.