Lorsque vous utilisez des sockets pour la programmation réseau dans PHP, socket_set_block () et socket_set_nonblock () sont deux fonctions très importantes qui contrôlent respectivement les prises de blocage et le mode non bloquant respectivement. Mais de nombreux développeurs ignorent un point clé après l'avoir réglé sur le mode de blocage:.
Alors la question est, que se passe-t-il si vous utilisez socket_set_block () mais oubliez de définir le délai d'expiration? Le programme sera-t-il bloqué? Cet article répondra en détail à cette question.
Lorsque vous utilisez socket_set_block ($ socket) pour définir le socket sur le mode de blocage, les opérations de lecture et d'écriture suivantes (telles que socket_read () , socket_recv () , socket_write () , etc.) bloqueront et attendent lorsque les données ne seront pas prêtes. Autrement dit, si vous essayez de lire une prise sans aucune donnée, le programme s'arrêtera à cette ligne de code jusqu'à ce que les données soient lisibles ou que la connexion soit déconnectée .
Ceci est utile dans certains scénarios où une "communication simultanée" est attendue. Mais une fois que le serveur externe répond lentement, voire en permanence, insensible (comme le temps d'arrêt du serveur cible, le blocage du réseau, le blocage par pare-feu, etc.), votre programme y sera bloqué et ne peut exécuter aucun code ultérieur .
Jetons un coup d'œil à un exemple:
<code> $ socket = socket_create (af_inet, sock_stream, sol_tcp); socket_set_block ($ socket); socket_connect ($ socket, 'gitbox.net', 80); socket_write ($ socket, "get / http / 1.0 \ r \ nhost: gitbox.net \ r \ n \ r \ n"); $ réponse = socket_read ($ socket, 2048);
Echo $ réponse;
</code>
Si gitbox.net est inaccessible ou ne renvoie aucune donnée du tout, la ligne de code socket_read () bloquera indéfiniment et que le programme sera "coincé".
La cause profonde de "Stuck" est qu'il n'y a pas de délai de délai de délai . Le mode de blocage lui-même n'est pas un problème, le problème est que la valeur de délai d'expiration dans socket_set_option () n'est pas définie.
PHP fournit deux paramètres de délai d'expiration:
Recevoir le délai
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec'=>5, 'usec'=>0]);
Envoyer le délai d'attente
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, ['sec'=>5, 'usec'=>0]);
Après les ajouter, même en mode blocage, les opérations de lecture et d'écriture n'attendent pas indéfiniment. Par exemple, le délai de réception est défini sur 5 secondes. Si aucune donnée n'est reçue dans les 5 secondes, socket_read () reviendra fausse et ne bloquera pas pour toujours.
Si vous oubliez de définir le délai d'expiration, il y a plusieurs conséquences potentielles:
Le serveur ne répond pas ou est coincé lorsqu'il est lent
L'utilisateur attend trop longtemps et a une très mauvaise expérience
Un blocage dans une tâche par lots fait que la tâche globale fait la queue ou même l'interruption.
Il est difficile de résoudre les problèmes, surtout lorsque le bogue ne se produit que lorsque le réseau est instable
Par conséquent, toute opération de réseau en mode blocage doit être utilisée avec un paramètre de délai d'attente clair .
Oui, si vous utilisez socket_set_block () et oubliez de définir le délai d'expiration, le programme peut en effet "périmé" dans certains cas. Ce n'est pas un bug dans PHP, mais un comportement de base du blocage des E / S dans la programmation réseau. L'utilisation rationnelle de socket_set_option () pour définir des délais d'attente est la clé pour garantir la robustesse et la réactivité du programme.
La meilleure pratique est: tant que vous entrez en mode de blocage, définissez immédiatement le délai d'expiration et ne comptez pas sur la fiabilité du serveur distant. Il s'agit d'une pensée fondamentale de la programmation défensive.