W3docs

Funzione PHP socket_set_timeout(): tutto quello che devi sapere

Scopri come usare socket_set_timeout() in PHP per impostare un timeout su operazioni di lettura/scrittura su stream e gestire connessioni lente.

Quando uno script legge da una connessione di rete, un server lento o non raggiungibile può lasciare PHP bloccato indefinitamente, occupando un worker e frustrando gli utenti. La funzione socket_set_timeout() imposta una scadenza sulle operazioni di lettura/scrittura in modo che una connessione bloccata fallisca rapidamente invece di restare in attesa. Questo articolo spiega esattamente cosa controlla, le insidie più comuni e come rilevare un timeout quando si verifica.

Cosa fa la funzione socket_set_timeout()

socket_set_timeout() imposta il timeout per le operazioni di I/Ofread(), fgets(), fwrite(), ecc. — su uno stream aperto con fsockopen() o pfsockopen(). Se una lettura o scrittura non si completa entro la scadenza, l'operazione termina anticipatamente e lo stream viene contrassegnato come scaduto.

Due cose che non fa:

  • Non influisce sul timeout di connessione. Questo è il quinto argomento di fsockopen($host, $port, $errno, $errstr, $connectTimeout). socket_set_timeout() governa solo il trasferimento dei dati dopo che la connessione è stata stabilita.
  • Non fa fallire la chiamata in modo evidente. Una lettura che va in timeout restituisce i dati ricevuti fino a quel momento (spesso una stringa vuota) e imposta un flag — devi verificare quel flag manualmente con stream_get_meta_data().

Attenzione al nome: nonostante il prefisso socket_, questa funzione appartiene alla famiglia degli stream, non all'estensione Sockets. Funziona su risorse di fsockopen(), mai su una risorsa di socket_create(). Da PHP 8.0 è un alias deprecato di stream_set_timeout() — preferisci quel nome nel nuovo codice.

Sintassi

socket_set_timeout(resource $stream, int $seconds, int $microseconds = 0): bool
ParametroDescrizione
$streamUna risorsa stream aperta restituita da fsockopen() o pfsockopen().
$secondsIl timeout in secondi interi.
$microsecondsTempo aggiuntivo in microsecondi (opzionale, predefinito 0).

Restituisce true in caso di successo e false in caso di errore (ad esempio, se $stream non è una risorsa stream valida).

Un esempio pratico

Apri una connessione, imposta un timeout di lettura di 5 secondi, poi verifica se una lettura è andata in timeout:

<?php

// Open a TCP connection to a web server.
$stream = fsockopen("www.example.com", 80, $errno, $errstr, 10);

if (!$stream) {
    echo "Connection failed: $errstr ($errno)\n";
    exit;
}

// Fail any single read/write that stalls for more than 5 seconds.
socket_set_timeout($stream, 5);

// Send a minimal HTTP request.
fwrite($stream, "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n");

// Read the first line of the response.
$line = fgets($stream, 1024);

// Check whether that read hit the timeout.
$info = stream_get_meta_data($stream);

if ($info['timed_out']) {
    echo "Read timed out — the server was too slow.\n";
} else {
    echo "First response line: " . trim($line) . "\n";
}

fclose($stream);

L'elemento chiave è la chiamata a stream_get_meta_data(): il suo elemento timed_out è l'unico modo affidabile per distinguere un timeout reale da una connessione che si è semplicemente chiusa.

Lettura in un ciclo

Quando leggi un'intera risposta, controlla timed_out a ogni iterazione in modo che un blocco a metà trasferimento non tronchi silenziosamente i tuoi dati:

<?php

$stream = fsockopen("www.example.com", 80, $errno, $errstr, 10);
socket_set_timeout($stream, 5);

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

$body = "";
while (!feof($stream)) {
    $chunk = fgets($stream, 4096);
    $info  = stream_get_meta_data($stream);

    if ($info['timed_out']) {
        echo "Stalled before the response finished.\n";
        break;
    }
    $body .= $chunk;
}

fclose($stream);
echo "Received " . strlen($body) . " bytes.\n";

Insidie comuni

  • Tipo di risorsa errato. Passare una risorsa di socket_create() non produce risultati utili — usa stream_set_timeout() con i socket di socket_create(), oppure socket_set_option() per SO_RCVTIMEO/SO_SNDTIMEO.
  • Confondere il timeout di connessione con quello di lettura. Un lungo timeout di connessione con fsockopen() non ti salverà da una risposta lenta; hai bisogno di entrambi.
  • Dimenticare di controllare timed_out. Senza questo controllo, una lettura andata in timeout appare esattamente come la fine regolare dello stream, portando a dati silenziosamente troncati.

Funzioni correlate

Conclusione

socket_set_timeout() evita che letture e scritture di rete lente blocchino il tuo script PHP. Ricorda che funziona sugli stream di fsockopen() (non sull'estensione Sockets), governa l'I/O piuttosto che la connessione, e che devi ispezionare il flag timed_out di stream_get_meta_data() per sapere se un timeout si è effettivamente verificato. Nel nuovo codice, usa il nome moderno stream_set_timeout().

Esercizio

Pratica
Cosa fa la funzione socket_set_timeout() in PHP?
Cosa fa la funzione socket_set_timeout() in PHP?
Was this page helpful?