W3docs

Funzione PHP socket_set_blocking(): Tutto Quello che Devi Sapere

Scopri come controllare la modalità bloccante e non bloccante dei socket in PHP con socket_set_blocking() e le sue alternative moderne.

Quando si scrive codice di rete in PHP, spesso è necessario controllare se una chiamata I/O attende i dati (bloccante) o ritorna immediatamente (non bloccante). La funzione socket_set_blocking() era l'alias storico per impostare questa modalità. È stata deprecata in PHP 8.1 e non dovrebbe essere utilizzata nel nuovo codice.

Il punto cruciale è che la sostituzione corretta dipende dal tipo di connessione in uso, ed è qui che molte guide sbagliano:

  • Se hai usato l'estensione Sockets (socket_create(), che restituisce un oggetto Socket), usa socket_set_nonblock() e socket_set_block().
  • Se hai usato uno stream (fsockopen() o stream_socket_client(), che restituiscono una risorsa stream), usa stream_set_blocking().

socket_set_blocking() era in realtà un alias di stream_set_blocking(), quindi ha sempre funzionato solo sulle risorse stream — mai sugli oggetti Socket. Questa distinzione è fondamentale per evitare un TypeError a runtime.

Modalità Bloccante vs. Non Bloccante

In modalità bloccante (quella predefinita), una chiamata di lettura o scrittura mette in pausa l'esecuzione dello script fino al completamento dell'operazione. Un socket_read() su un socket vuoto rimane in attesa finché non arrivano byte.

In modalità non bloccante, la stessa chiamata ritorna immediatamente. Se non ci sono dati pronti, restituisce un risultato vuoto (o false) invece di attendere. Questo consente a un singolo script di gestire molte connessioni o di rimanere reattivo, al costo di dover eseguire il polling e verificare se i dati sono effettivamente arrivati.

Usa la modalità bloccante quando…Usa la modalità non bloccante quando…
Gestisci una connessione alla voltaServi molti client in un unico ciclo
La semplicità conta più della velocitàLo script deve rimanere reattivo
Una richiesta/risposta breve e prevedibileImplementi il tuo ciclo di polling/eventi

Impostare la Modalità su un Oggetto Socket

Se hai creato la connessione con l'estensione Sockets, usa socket_set_nonblock() e socket_set_block():

socket_set_nonblock(Socket $socket): bool
socket_set_block(Socket $socket): bool

Entrambe restituiscono true in caso di successo e false in caso di errore. Un esempio completo ed eseguibile con gestione degli errori e pulizia:

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("Socket creation failed: " . socket_strerror(socket_last_error()) . "\n");
}

// Switch to non-blocking mode
if (!socket_set_nonblock($socket)) {
    die("Failed to set non-blocking mode\n");
}
echo "Socket is now non-blocking.\n";

// ... perform non-blocking socket operations ...

// Switch back to blocking mode if needed
socket_set_block($socket);
echo "Socket is now blocking again.\n";

socket_close($socket);

Non chiamare stream_set_blocking($socket, false) su un oggetto Socketsocket_create() restituisce un'istanza Socket, e stream_set_blocking() accetta solo una risorsa stream. Passare un Socket genera un TypeError.

Impostare la Modalità su uno Stream

Se hai aperto la connessione con fsockopen() o stream_socket_client(), hai una risorsa stream e dovresti usare stream_set_blocking():

stream_set_blocking(resource $stream, bool $enable): bool
  • $stream: la risorsa stream da configurare.
  • $enable: true per la modalità bloccante, false per la modalità non bloccante.
<?php

$stream = stream_socket_client('tcp://example.com:80', $errno, $errstr, 5);
if ($stream === false) {
    die("Connect failed: $errstr ($errno)\n");
}

// Switch the stream to non-blocking mode
if (!stream_set_blocking($stream, false)) {
    die("Failed to set non-blocking mode\n");
}
echo "Stream is now non-blocking.\n";

fclose($stream);

Un Ciclo di Lettura Non Bloccante

La modalità non bloccante è utile solo se esegui il polling. Un pattern tipico invia una richiesta, poi verifica ripetutamente la presenza di una risposta senza bloccare lo script:

<?php

$stream = stream_socket_client('tcp://example.com:80', $errno, $errstr, 5);
if ($stream === false) {
    die("Connect failed: $errstr ($errno)\n");
}

stream_set_blocking($stream, false);
fwrite($stream, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");

$response = '';
$start = time();
while (!feof($stream) && time() - $start < 5) {
    $chunk = fread($stream, 8192);
    if ($chunk === '' || $chunk === false) {
        // No data yet — do other work or wait briefly
        usleep(50000); // 50 ms
        continue;
    }
    $response .= $chunk;
}

echo substr($response, 0, 15), "\n"; // e.g. "HTTP/1.1 200 OK"
fclose($stream);

La chiamata usleep() impedisce un ciclo attivo intensivo che monopolizzerebbe la CPU. In produzione si sostituirebbe generalmente questo polling manuale con stream_select() per attendere in modo efficiente su più stream contemporaneamente.

Note sulla Versione

  • PHP 8.1: socket_set_blocking() è deprecata. Chiamarla emette un avviso di deprecazione.
  • La funzione era un alias di stream_set_blocking(), quindi non ha mai accettato oggetti Socket.
  • Per gli oggetti Socket, socket_set_nonblock() / socket_set_block() sono sempre state le chiamate corrette e rimangono supportate.

Funzioni Correlate

  • socket_get_status() — ispeziona lo stato di un socket, incluso se è bloccato.
  • socket_set_timeout() — controlla per quanto tempo un'operazione bloccante attende prima di rinunciare.
  • PHP Streams — l'API streams più ampia a cui appartiene stream_set_blocking().

Conclusione

Controllare la modalità bloccante di una connessione è essenziale per costruire applicazioni di rete PHP reattive. La chiave è abbinare la funzione al tipo di connessione: usa socket_set_nonblock() / socket_set_block() per gli oggetti Socket, e stream_set_blocking() per le risorse stream. Evita la deprecata socket_set_blocking() nel nuovo codice e ricorda che la modalità non bloccante è utile solo quando viene abbinata a un ciclo di polling.

Esercitazione

Pratica
In PHP, cosa fa la funzione socket_set_blocking()?
In PHP, cosa fa la funzione socket_set_blocking()?
Was this page helpful?