stream_socket_server în PHP

Socket-uri PHP 5.0+

Creează un socket de server care ascultă pe o adresă și un port, pentru conexiuni primite cu stream_socket_accept.

Sintaxă
stream_socket_server(string $address, &$error_code = null, &$error_message = null, int $flags = 12, $context = null)

Ce face stream_socket_server

stream_socket_server deschide un port pe care alte programe se pot conecta. Conexiunile se primesc apoi cu stream_socket_accept. Așa se scriu în PHP servere mici: un serviciu de chat, un server de test, un worker care primește comenzi.

Adresa tcp://127.0.0.1:8000 acceptă doar conexiuni de pe aceeași mașină, iar tcp://0.0.0.0:8000 din toată rețeaua. Portul 0 cere sistemului un port liber. Flag-urile implicite (12) sunt STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; pentru UDP folosește doar STREAM_SERVER_BIND.

Parametri

Parametru Descriere
$address Adresa de ascultare, de exemplu tcp://0.0.0.0:8000 sau udp://127.0.0.1:9000.
$error_code Opțional. Variabilă pentru codul erorii.
$error_message Opțional. Variabilă pentru mesajul erorii.
$flags Opțional. Implicit STREAM_SERVER_BIND | STREAM_SERVER_LISTEN.
$context Opțional. Context, de exemplu cu certificatul pentru un server tls://.

Ce returnează

Socket-ul serverului sau false la eroare (de exemplu port ocupat).

Exemple

Exemplul 1: Server pe un port ales de sistem

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

echo "Ascult pe $ip\n";
echo "Port valid: " . ($port > 0 ? "da" : "nu");

Rezultat

Ascult pe 127.0.0.1
Port valid: da

Exemplul 2: Un server care răspunde cu majuscule

Ca exemplul să ruleze singur, clientul este în același script. Într-un server real, stream_socket_accept stă într-o buclă și așteaptă clienți din alte programe.

<?php
$server = stream_socket_server("tcp://127.0.0.1:0", $cod, $mesaj);
$client = stream_socket_client("tcp://" . stream_socket_get_name($server, false));

fwrite($client, "salut din arad\n");

$conexiune = stream_socket_accept($server);
$cerere = fgets($conexiune);
fwrite($conexiune, strtoupper($cerere));
fclose($conexiune);

echo fgets($client);

Rezultat

SALUT DIN ARAD

Exemplul 3: Port deja ocupat

<?php
$primul = stream_socket_server("tcp://127.0.0.1:0");
$adresa = stream_socket_get_name($primul, false);

$al_doilea = @stream_socket_server("tcp://$adresa", $cod, $mesaj);
var_dump($al_doilea);
echo $mesaj;

Rezultat

bool(false)
Address already in use

Greșeli frecvente

  • Asculți pe 0.0.0.0 pentru un serviciu intern. Portul devine accesibil din toată rețeaua. Pentru servicii locale, folosește 127.0.0.1.
  • Alegi un port sub 1024 (de exemplu 80). Pe Linux și macOS ai nevoie de drepturi de root; folosește un port peste 1024.
  • Creezi un server UDP cu flag-urile implicite. STREAM_SERVER_LISTEN nu are sens la UDP și funcția eșuează. Dă STREAM_SERVER_BIND.

Comenzi înrudite

  • stream_socket_accept: Așteaptă și acceptă o conexiune nouă pe un socket de server; returnează stream-ul pentru acel client.
  • stream_socket_client: Deschide o conexiune către un server dată ca adresă completă (tcp://, udp://, tls://, unix://) și o returnează ca stream.
  • stream_socket_get_name: Returnează adresa locală sau adresa celuilalt capăt al unui socket, în forma ip:port.
  • stream_select: Așteaptă până când unul sau mai multe stream-uri (socket-uri, pipe-uri) au date de citit sau pot primi date.