stream_socket_sendto / stream_socket_recvfrom în PHP

Socket-uri PHP 5.0+

Trimite și primește mesaje pe un socket, mai ales UDP, aflând sau alegând adresa celuilalt capăt.

Sintaxă
stream_socket_sendto($socket, string $data, int $flags = 0, string $address = ''): int|false

Ce face stream_socket_sendto / stream_socket_recvfrom

La UDP nu există o conexiune permanentă, ci mesaje separate. Serverul primește un mesaj cu stream_socket_recvfrom, care îi spune și de la ce adresă a venit, apoi răspunde cu stream_socket_sendto la acea adresă.

stream_socket_recvfrom primește $length (câți octeți să citească) și, opțional, flag-ul STREAM_PEEK, care citește mesajul fără să-l scoată din coadă. Pe socket-uri conectate (TCP sau UDP cu stream_socket_client), adresa poate lipsi.

Parametri

Parametru Descriere
$socket Socket-ul folosit.
$data Datele trimise.
$flags Opțional. STREAM_OOB pentru date urgente; la recvfrom și STREAM_PEEK.
$address Opțional. Adresa destinației, ip:port. La recvfrom, variabila în care primești adresa expeditorului.

Ce returnează

sendto: numărul de octeți trimiși sau false. recvfrom: datele primite sau false.

Exemple

Exemplul 1: Ping și pong prin UDP

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

fwrite($client, "ping");

$primit = stream_socket_recvfrom($server, 1500, 0, $expeditor);
echo "Serverul a primit: $primit de la " . explode(":", $expeditor)[0] . "\n";

$trimis = stream_socket_sendto($server, "pong", 0, $expeditor);
echo "Octeți trimiși: $trimis\n";
echo "Clientul a primit: " . fread($client, 1500);

Rezultat

Serverul a primit: ping de la 127.0.0.1
Octeți trimiși: 4
Clientul a primit: pong

Exemplul 2: Te uiți la mesaj fără să-l scoți

Cu STREAM_PEEK mesajul rămâne în coadă, așa că al doilea apel îl primește din nou.

<?php
$server = stream_socket_server("udp://127.0.0.1:0", $cod, $mesaj, STREAM_SERVER_BIND);
$client = stream_socket_client("udp://" . stream_socket_get_name($server, false));
fwrite($client, "comanda 17");

var_dump(stream_socket_recvfrom($server, 1500, STREAM_PEEK));
var_dump(stream_socket_recvfrom($server, 1500));

Rezultat

string(10) "comanda 17"
string(10) "comanda 17"

Greșeli frecvente

  • Citești un mesaj UDP cu un $length prea mic. Restul mesajului se pierde: din „direct” cu lungimea 3 primești doar „dir”, iar următorul apel nu primește restul.

Comenzi înrudite

  • stream_socket_server: Creează un socket de server care ascultă pe o adresă și un port, pentru conexiuni primite cu stream_socket_accept.
  • stream_socket_client: Deschide o conexiune către un server dată ca adresă completă (tcp://, udp://, tls://, unix://) și o returnează ca stream.
  • fsockopen / pfsockopen: Deschide o conexiune TCP (sau UDP, SSL) către un server și o returnează ca stream, pentru fwrite și fgets.