W3docs

Fonction PHP socket_set_blocking() : tout ce que vous devez savoir

Apprenez à contrôler le mode bloquant ou non bloquant d'un socket PHP avec socket_set_blocking(), dépréciée en PHP 8.1, et ses remplaçants modernes.

Lorsque vous écrivez du code réseau en PHP, vous devez souvent contrôler si un appel d'E/S attend des données (mode bloquant) ou retourne immédiatement (mode non bloquant). La fonction socket_set_blocking() était l'alias historique pour définir ce mode. Elle a été dépréciée en PHP 8.1 et ne doit pas être utilisée dans du nouveau code.

Le piège est que le bon remplacement dépend du type de connexion que vous avez, et c'est là que de nombreux guides se trompent :

  • Si vous avez utilisé l'extension Sockets (socket_create(), qui retourne un objet Socket), utilisez socket_set_nonblock() et socket_set_block().
  • Si vous avez utilisé un flux (fsockopen() ou stream_socket_client(), qui retournent une ressource de flux), utilisez stream_set_blocking().

socket_set_blocking() était en réalité un alias de stream_set_blocking(), donc elle n'a jamais fonctionné que sur des ressources de flux — jamais sur des objets Socket. Cette distinction est la clé pour éviter une TypeError à l'exécution.

Mode bloquant et mode non bloquant

En mode bloquant (le mode par défaut), un appel de lecture ou d'écriture suspend l'exécution du script jusqu'à ce que l'opération puisse se terminer. Un socket_read() sur un socket vide attend simplement que des octets arrivent.

En mode non bloquant, le même appel retourne immédiatement. Si aucune donnée n'est prête, il retourne un résultat vide (ou false) au lieu d'attendre. Cela permet à un seul script de gérer plusieurs connexions ou de rester réactif — au prix d'avoir à interroger et vérifier si des données sont effectivement arrivées.

Utilisez le mode bloquant quand…Utilisez le mode non bloquant quand…
Vous gérez une connexion à la foisVous servez plusieurs clients dans une boucle
La simplicité prime sur le débitLe script doit rester réactif
Une requête/réponse courte et prévisibleVous implémentez votre propre boucle de sondage/événements

Définir le mode sur un objet Socket

Si vous avez créé la connexion avec l'extension Sockets, utilisez socket_set_nonblock() et socket_set_block() :

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

Les deux retournent true en cas de succès et false en cas d'échec. Un exemple complet et exécutable avec gestion des erreurs et nettoyage :

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

N'appelez pas stream_set_blocking($socket, false) sur un objet Socketsocket_create() retourne une instance Socket, et stream_set_blocking() n'accepte qu'une ressource de flux. Passer un objet Socket lève une TypeError.

Définir le mode sur un flux

Si vous avez ouvert la connexion avec fsockopen() ou stream_socket_client(), vous disposez d'une ressource de flux et devez utiliser stream_set_blocking() :

stream_set_blocking(resource $stream, bool $enable): bool
  • $stream : la ressource de flux à configurer.
  • $enable : true pour le mode bloquant, false pour le mode non bloquant.
<?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);

Une boucle de lecture non bloquante

Le mode non bloquant n'est utile que si vous interrogez le socket. Un schéma typique envoie une requête, puis vérifie répétitivement la réponse sans bloquer le 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);

L'appel usleep() empêche une boucle occupée serrée de monopoliser le CPU. En production, vous remplaceriez généralement ce sondage manuel par stream_select() pour attendre efficacement sur plusieurs flux à la fois.

Notes de version

  • PHP 8.1 : socket_set_blocking() est dépréciée. L'appeler émet un avis de dépréciation.
  • La fonction était un alias de stream_set_blocking(), donc elle n'a jamais accepté d'objets Socket.
  • Pour les objets Socket, socket_set_nonblock() / socket_set_block() ont toujours été les appels corrects et restent pris en charge.

Fonctions associées

  • socket_get_status() — inspecter l'état d'un socket, notamment s'il est bloqué.
  • socket_set_timeout() — contrôler combien de temps une opération bloquante attend avant d'abandonner.
  • PHP Streams — l'API de flux plus large à laquelle appartient stream_set_blocking().

Conclusion

Contrôler le mode bloquant d'une connexion est essentiel pour créer des applications réseau PHP réactives. La clé est d'associer la fonction au type de connexion : utilisez socket_set_nonblock() / socket_set_block() pour les objets Socket, et stream_set_blocking() pour les ressources de flux. Évitez la fonction dépréciée socket_set_blocking() dans le nouveau code, et n'oubliez pas que le mode non bloquant ne porte ses fruits que si vous l'associez à une boucle de sondage.

Pratique

Pratique
En PHP, que fait la fonction socket_set_blocking() ?
En PHP, que fait la fonction socket_set_blocking() ?
Was this page helpful?