Dans la programmation du réseau PHP, la fonction Stream_Socket_Shutdown est utilisée pour fermer une certaine direction (lire, écrire ou les deux) d'une connexion à socket. Cependant, dans une utilisation réelle, de nombreux développeurs rencontrent des problèmes tels que l'interruption de connexion anormale, les erreurs du client et même la perte de données après l'appel Stream_Socket_Shutdown . Cet article analysera le mécanisme de travail de Stream_Socket_Shutdown en profondeur, explorera les causes des exceptions de connexion et donnera des méthodes pour éviter et réparer.
La définition de la fonction de Stream_Socket_Shutdown est la suivante:
bool stream_socket_shutdown(resource $stream, int $how)
$ Stream : une ressource de flux de socket ouvert.
$ comment : fermez la direction, prenez la valeur:
Stream_shut_rd (0) Fermez la direction de lecture
Stream_shut_wr (1) Fermez la direction d'écriture
Stream_shut_rdwr (2) désactiver les instructions de lecture et d'écriture
Par exemple:
$socket = stream_socket_client("tcp://m66.net:8080", $errno, $errstr, 30);
if (!$socket) {
die("Échec de la connexion: $errstr ($errno)");
}
// Fermez la direction d'écriture,Indique que les données ne sont plus envoyées
stream_socket_shutdown($socket, STREAM_SHUT_WR);
Après avoir appelé Stream_Socket_Shutdown , une certaine direction de la prise sera fermée et le noyau enverra des paquets de finition au pair, indiquant que la connexion est fermée.
La cause profonde de l'exception est que lors de l'utilisation de Stream_Socket_Shutdown , le client ou le serveur ne gère pas correctement le signal d'arrêt de la connexion, ou l'ordre de clôture est inapproprié. Spécifiquement se manifeste comme:
Fermez la direction d'écriture à l'avance , ce qui entraîne la déconnexion de la connexion lorsque le pair ne termine pas la lecture des données.
Dans le même temps, la direction de lecture et d'écriture est désactivée , mais les données ne sont pas lues, entraînant une perte de données.
Après la fermeture de la direction d'écriture, les données restantes ne sont pas lues dans le temps , ce qui entraîne une connexion anormale.
Le paquet de nageoires n'est pas traité par le pair, provoquant la connexion au délai d'attente et à la déconnexion .
Ces problèmes sont particulièrement susceptibles de se produire dans les scénarios de communication à longue connexion TCP ou à demi-duplex.
Si vous envoyez simplement les données et ne prévoyez pas de les rédiger, appelez:
stream_socket_shutdown($socket, STREAM_SHUT_WR);
Cela signifie que la direction d'écriture est fermée, mais la direction de lecture est toujours conservée, en attendant les données envoyées par le pair.
Si le serveur et le client doivent d'abord désactiver la direction d'écriture, assurez-vous que le pair a suffisamment de temps pour lire les données restantes.
Après la fermeture de la direction d'écriture, la connexion peut toujours lire les données. L'approche générale est:
// Fermez la direction d'écriture
stream_socket_shutdown($socket, STREAM_SHUT_WR);
// Continuez à lire les données des pairs jusqu'àEOF
while (!feof($socket)) {
$data = fread($socket, 8192);
if ($data === false) {
break;
}
// Traitement des données
}
Assurez-vous qu'aucune donnée héritée n'est lue.
Tout d'abord, fermez la direction d'écriture et informez les données des pairs à envoyer.
Lisez les données que le pair peut retourner.
Après avoir lu, fermez la direction de lecture ou fermez toute la connexion.
Utilisez Stream_Set_timeout pour définir le délai d'expiration de lecture et d'écriture pour éviter le blocage de la connexion.
L'exemple suivant démontre la bonne façon d'écrire une connexion sécurisée sur le serveur:
$server = stream_socket_server("tcp://0.0.0.0:12345", $errno, $errstr);
if (!$server) {
die("Impossible de démarrer le serveur: $errstr ($errno)");
}
$client = stream_socket_accept($server);
if ($client) {
// Envoyer des données de réponse
fwrite($client, "Hello from server\n");
// Fermez la direction d'écriture,Informer le client qu'il n'y a plus de données
stream_socket_shutdown($client, STREAM_SHUT_WR);
// Continuez à lire les données envoyées par le client
while (!feof($client)) {
$data = fread($client, 8192);
if ($data === false || $data === "") {
break;
}
echo "Données du client reçu: $data\n";
}
// Fermer la connexion
fclose($client);
}
fclose($server);
Évitez de désactiver la lecture et d'écrire des instructions simultanément à moins qu'il ne soit sûr que la communication ne sera plus effectuée.
Pour les longues connexions, évitez les appels fréquents vers Stream_Socket_Shutdown et utilisez raisonnablement les packages de battements de cœur et le délai d'expiration.
Assurez-vous que la conception du protocole du client et du serveur est claire sur le calendrier et la clôture de la connexion.
Utilisez Stream_Set_Blocking et Stream_Set_timeout pour éviter le blocage.
Stream_Socket_Shutdown est un outil important pour clôturer les connexions de socket, mais une utilisation inappropriée peut facilement conduire à des interruptions de connexion anormales. Comprendre la sémantique de sa fermeture, sélectionner raisonnablement la direction de fermeture et garantir l'ordre de lecture et d'écriture des données après la fermeture est la clé pour éviter et résoudre les problèmes. La combinaison des paramètres de délai d'expiration corrects et de la gestion des exceptions peut rendre les programmes de réseau PHP plus stables et fiables.