Position actuelle: Accueil> Derniers articles> Pourquoi le programme est-il toujours non bloqué après que socket_set_block est défini?

Pourquoi le programme est-il toujours non bloqué après que socket_set_block est défini?

gitbox 2025-05-29

Pourquoi le programme PHP apparaît-il toujours en mode non bloquant après avoir appelé la fonction socket_set_block?

Lorsque vous utilisez la programmation de socket en PHP, la fonction SOCKET_SET_BLOCK est généralement utilisée pour définir Socket sur le mode de blocage. Il est prévu que les opérations de lecture et d'écriture ultérieures puissent "attendre" l'achèvement des données avant de continuer l'exécution. Cependant, de nombreux développeurs rencontreront le problème: après avoir appelé socket_set_block , le programme semble toujours non bloquant et les opérations de lecture et d'écriture n'attendront pas, mais reviendront immédiatement. Pourquoi est-ce? Cet article analysera les raisons derrière elle en profondeur et donnera des solutions correspondantes.

1. Les fonctions et limites de socket_set_block

La fonction de socket_set_block consiste à définir une prise sur le mode de blocage, c'est-à-dire lors de l'appel des fonctions liées et écrites, s'il n'y a pas de données à lire ou à écrire, l'appel sera bloqué jusqu'à ce qu'il y ait des données ou expirées. Sa signature de fonction est:

 bool socket_set_block ( resource $socket )

Renvoie True si l'appel réussit, sinon retournez faux .

Mais il est important de noter:

  • Socket_Set_Block est un mode de blocage défini pour la ressource de socket sous-jacente, et son effet dépend de l'état spécifique de la prise.

  • Si le socket est déjà en mode non bloquant (par exemple, socket_set_nonblock a été appelé auparavant), le blocage doit être repris après l'appel socket_set_block .

  • Cependant, si la prise elle-même est dans un état spécial (comme déjà connecté ou un état sous-jacent système), le réglage du mode de blocage peut ne pas prendre effet.

2. Pourquoi le programme apparaît-il toujours en mode non bloquant?

  1. La prise sous-jacente est réinitialisée à un état non bloquant par un autre code

Il peut y avoir d'autres code ou cadres dans le programme qui entrent en conflit avec les paramètres de socket. Par exemple, avant d'appeler socket_set_block , certaines bibliothèques ou middleware peuvent appeler socket_set_nonblock , et même l'appel système sous-jacent modifie les propriétés de socket, ce qui entraîne des appels ultérieurs invalides.

  1. La connexion au socket est dans un état asynchrone ou délai

Dans certains systèmes d'exploitation ou versions PHP, le paramètre de mode de blocage de la prise peut ne pas prendre effet si la prise est en connexion ou si un délai d'expiration se produit. Par exemple:

  • L'appel des opérations de lecture et d'écriture ne bloquera pas lorsque la connexion n'est pas terminée.

  • Les types de socket non standard (tels que la prise de domaine UNIX, la prise SSL) prennent en charge le mode de blocage de façon incohérente.

  1. PHP Version et problèmes de compatibilité du système d'exploitation

Différentes versions de PHP peuvent différer dans la mise en œuvre sous-jacente des fonctions de socket. En particulier, le comportement des plates-formes Windows et Linux est également différente.

  1. Ordre d'appel incorrect

Si socket_set_block est appelé en premier, mais d'autres fonctions qui définissent l'état de blocage / non bloquant sont appelées ultérieurement, la commutation d'état ne sera pas valide.

  1. Les fonctions utilisées dans le code sont elles-mêmes conçues pour ne pas bloquer

Par exemple, en utilisant socket_select ou en utilisant des fonctions de fonctionnement de flux non bloquant, même si la prise est dans un état de blocage, cela affectera les performances du programme.

3. Comment utiliser correctement socket_set_block ?

  • Assurez-vous de l'appeler une seule fois et dans un endroit raisonnable

L'appel socket_set_block doit être placé après la création et la connexion avec succès de socket, et assurez-vous qu'aucun code ultérieur ne remplace ce paramètre.

 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, "gitbox.net", 80);
socket_set_block($socket);
  • Combiné à la vérification des erreurs

Vérifiez si l'appel de fonction renvoie true et vérifiez s'il y a une erreur système ou socket.

 if (!socket_set_block($socket)) {
    $errorcode = socket_last_error($socket);
    $errormsg = socket_strerror($errorcode);
    echo "Le blocage du réglage a échoué: [$errorcode] $errormsg\n";
}
  • Évitez d'utiliser des fonctions non bloquantes pour mélanger

Ne mélangez pas Socket_Set_Block et Socket_Set_NonBlock pour éviter la confusion de l'état.

Si vous utilisez le socket d'encapsulation Stream de PHP, vous pouvez utiliser Stream_Set_Blocking pour contrôler le mode de blocage.

 $stream = stream_socket_client("tcp://gitbox.net:80", $errno, $errstr, 30);
stream_set_blocking($stream, true);

4. Exemple de code

L'exemple suivant montre comment configurer correctement une prise de blocage et envoyer une demande HTTP:

 <?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("créerSocketéchouer: " . socket_strerror(socket_last_error()) . "\n");
}

$result = socket_connect($socket, "gitbox.net", 80);
if ($result === false) {
    die("连接échouer: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// Définir le mode de blocage
if (!socket_set_block($socket)) {
    die("Le blocage du réglage a échoué: " . socket_strerror(socket_last_error($socket)) . "\n");
}

$request = "GET / HTTP/1.1\r\nHost: gitbox.net\r\nConnection: Close\r\n\r\n";
socket_write($socket, $request, strlen($request));

// Blocs lors de la lecture des données,Jusqu&#39;à ce que le contenu soit reçu ou que la connexion soit fermée
$response = '';
while ($out = socket_read($socket, 2048)) {
    $response .= $out;
}

echo $response;

socket_close($socket);

5. Résumé

  • La fonction de socket_set_block est de définir Socket sur bloquer, mais il n'est pas omnipotent et est affecté par divers facteurs tels que l'état lui-même, le système d'exploitation, la version PHP et l'ordre des appels.

  • L'appel socket_set_block affiche toujours le non-blocage, généralement parce que l'état est couvert par un autre code, l'état de connexion est spécial ou que l'implémentation sous-jacente est différente.

  • L'approche correcte consiste à contrôler strictement le processus de configuration de blocage de la prise pour éviter de mélanger les appels pour bloquer et les fonctions de configuration non bloquantes.

  • Comprenez les différences dans le socket sous-jacent et l'environnement PHP et combinez les problèmes de positionnement des informations de débogage.

La maîtrise de ces points clés peut vous aider à contrôler plus de manière stable le comportement de blocage des douilles en PHP et à éviter des performances asynchrones inattendues.