W3docs

Fonction PHP socket_set_timeout() : Tout ce que vous devez savoir

Découvrez la fonction socket_set_timeout() en PHP pour définir un délai d'expiration sur les flux réseau et éviter les blocages indéfinis.

Lorsque votre script lit depuis une connexion réseau, un serveur lent ou mort peut laisser PHP bloquer indéfiniment, monopolisant un processus de travail et frustrant les utilisateurs. La fonction socket_set_timeout() définit une limite de temps sur les opérations de lecture/écriture, de sorte qu'une connexion bloquée échoue rapidement au lieu de rester suspendue. Cet article explique précisément ce qu'elle contrôle, les pièges courants et comment détecter un délai d'expiration lorsqu'il se produit.

Ce que fait la fonction socket_set_timeout()

socket_set_timeout() définit le délai d'expiration pour les opérations d'E/Sfread(), fgets(), fwrite(), etc. — sur un flux ouvert avec fsockopen() ou pfsockopen(). Si une lecture ou une écriture ne se termine pas dans le délai imparti, l'opération se termine prématurément et le flux est marqué comme ayant expiré.

Deux choses qu'elle ne fait pas :

  • Elle n'affecte pas le délai d'expiration de la connexion. C'est le cinquième argument de fsockopen($host, $port, $errno, $errstr, $connectTimeout). socket_set_timeout() régit uniquement le transfert de données une fois la connexion établie.
  • Elle ne fait pas échouer l'appel de manière bruyante. Une lecture dont le délai expire renvoie les données reçues jusqu'à présent (souvent une chaîne vide) et définit un indicateur — vous devez inspecter cet indicateur vous-même avec stream_get_meta_data().

Piège de nommage : Malgré le préfixe socket_, cette fonction appartient à la famille des flux, et non à l'extension Sockets. Elle fonctionne sur les ressources issues de fsockopen(), jamais sur une ressource issue de socket_create(). Depuis PHP 8.0, il s'agit d'un alias déprécié de stream_set_timeout() — préférez ce nom dans le nouveau code.

Syntaxe

socket_set_timeout(resource $stream, int $seconds, int $microseconds = 0): bool
ParamètreDescription
$streamUne ressource de flux ouverte retournée par fsockopen() ou pfsockopen().
$secondsLe délai d'expiration en secondes entières.
$microsecondsTemps supplémentaire en microsecondes (optionnel, par défaut 0).

Elle retourne true en cas de succès et false en cas d'échec (par exemple, si $stream n'est pas une ressource de flux valide).

Un exemple fonctionnel

Ouvrez une connexion, définissez un délai d'expiration de lecture de 5 secondes, puis vérifiez si une lecture a expiré :

<?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'élément clé est l'appel à stream_get_meta_data() : son élément timed_out est le seul moyen fiable de distinguer un véritable délai d'expiration d'une connexion qui s'est simplement fermée.

Lecture en boucle

Lorsque vous lisez une réponse entière, vérifiez timed_out à chaque itération pour qu'un blocage en cours de transfert ne tronque pas silencieusement vos données :

<?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";

Pièges courants

  • Mauvais type de ressource. Passer une ressource socket_create() ne sert à rien — utilisez stream_set_timeout() avec les sockets socket_create(), ou socket_set_option() pour SO_RCVTIMEO/SO_SNDTIMEO.
  • Confusion entre délai de connexion et délai de lecture. Un long délai de connexion fsockopen() ne vous protégera pas d'une réponse lente ; vous avez besoin des deux.
  • Oublier de vérifier timed_out. Sans cela, une lecture expirée ressemble exactement à une fin de flux normale, entraînant une troncature silencieuse des données.

Fonctions associées

Conclusion

socket_set_timeout() empêche les lectures et écritures réseau lentes de bloquer votre script PHP. N'oubliez pas qu'elle fonctionne sur les flux fsockopen() (pas l'extension Sockets), régit les E/S plutôt que la connexion, et que vous devez inspecter l'indicateur timed_out de stream_get_meta_data() pour savoir si un délai d'expiration s'est réellement produit. Dans le nouveau code, préférez son nom moderne, stream_set_timeout().

Pratique

Pratique
Que fait la fonction socket_set_timeout() en PHP ?
Que fait la fonction socket_set_timeout() en PHP ?
Was this page helpful?