Lors de l'exploitation des prises de réseau dans PHP, la gestion des erreurs a toujours été un mal de tête. PHP fournit une fonction socket_clear_error () , mais la documentation officielle explique très brièvement ses scénarios d'utilisation, ce qui rend de nombreux développeurs peu clairs quand utiliser cette fonction.
Cet article combinera des cas réels pour vous aider à trier les scénarios applicables de socket_clear_error () , et donner des exemples de la façon de l'utiliser pour gérer les erreurs de socket plus élégamment.
socket_clear_error () est une fonction dans l'extension de socket de PHP qui est spécifiquement utilisée pour nettoyer l'état d'erreur de connexion du socket actuel. Autrement dit, il peut "réinitialiser" l'indicateur d'erreur de la connexion de socket.
Dans le document officiel, socket_clear_error () n'écrit que la signature de la fonction et une description de la phrase:
bool socket_clear_error ( resource $socket )
Effacer l'état d'erreur de socket.
Mais il ne spécifie pas quand il doit être appelé, ni quel effet cela apportera.
Pendant le processus de transmission du réseau, diverses erreurs peuvent se produire, telles que la déconnexion, l'échec de l'envoi de données et le blocage du réseau. La fonction de socket dans PHP renvoie généralement FALSE et définit un code d'erreur. Nous utilisons socket_last_error () pour obtenir le code d'erreur, puis utilisons socket_strorror () pour les convertir en informations lisibles.
Cependant, ces messages d'erreur "continueront" jusqu'à ce qu'ils soient nettoyés manuellement, sinon les opérations de socket ultérieures peuvent être affectées par l'erreur précédente, entraînant une erreur de jugement.
Pour donner un exemple simple:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, 'm66.net', 80);
socket_write($socket, "GET / HTTP/1.1\r\nHost: m66.net\r\n\r\n");
$errorCode = socket_last_error($socket);
if ($errorCode !== 0) {
echo "Une erreur s'est produite:" . socket_strerror($errorCode) . PHP_EOL;
socket_clear_error($socket); // Nettoyez l'état d'erreur,Évitez d'affecter les opérations ultérieures
}
// Continuer à utiliser $socket Faire autre chose
Si socket_clear_error () n'est pas appelé, les appels ultérieurs à socket_last_error () peuvent également renvoyer le code d'erreur précédent, provoquant une confusion dans le jugement logique.
En mode non bloquant, l'opération de socket n'attendra pas l'achèvement, et parfois le code d'erreur Eagain ou Ewouldblock est renvoyé pour indiquer que les données sont temporairement indisponibles. Cette erreur n'est pas un véritable échec, il indique simplement au programme d'essayer à nouveau plus tard.
Si l'état d'erreur n'est pas nettoyé, le programme pensera à tort qu'il y a un problème avec la connexion, ce qui entraîne la fermeture de la connexion à l'avance.
socket_set_nonblock($socket);
while (true) {
$data = socket_read($socket, 2048);
if ($data === false) {
$err = socket_last_error($socket);
if ($err === SOCKET_EAGAIN || $err === SOCKET_EWOULDBLOCK) {
socket_clear_error($socket);
// Pas de données pour le moment,Réessayer plus tard
usleep(100000);
continue;
} else {
// Autres erreurs,Processus ou sortie
break;
}
}
echo $data;
}
Une connexion de socket maintenue pendant longtemps peut rencontrer des erreurs temporaires plusieurs fois. Afin de s'assurer que les opérations ultérieures n'échoueront pas en raison de l'état d'erreur précédent, il est une bonne habitude d'appeler socket_clear_error () une fois l'opération terminée.
socket_clear_error () est une fonction pour nettoyer l'état d'erreur actuel de la prise.
Il est souvent utilisé dans la programmation de socket non bloquante pour éviter une erreur de jugement causée par une indisponibilité temporaire (Eagain / Ewouldblock).
Dans le multiplexage de connexion ou les scénarios de connexion longs, il peut également être utilisé pour garantir que l'état d'erreur est réinitialisé et que les opérations ultérieures sont normales.
S'il n'est pas appelé, l'état d'erreur sera conservé, ce qui a fait renvoyer un code d'erreur expiré à socket_last_error () , affectant la logique métier.
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) {
die("Impossible de créer socket: " . socket_strerror(socket_last_error()) . PHP_EOL);
}
if (!socket_connect($socket, 'm66.net', 80)) {
die("Échec de la connexion: " . socket_strerror(socket_last_error($socket)) . PHP_EOL);
}
socket_set_nonblock($socket);
$request = "GET / HTTP/1.1\r\nHost: m66.net\r\nConnection: close\r\n\r\n";
socket_write($socket, $request);
while (true) {
$data = socket_read($socket, 2048);
if ($data === false) {
$err = socket_last_error($socket);
if ($err === SOCKET_EAGAIN || $err === SOCKET_EWOULDBLOCK) {
socket_clear_error($socket);
usleep(100000); // attendez 0.1 Relisez en quelques secondes
continue;
} else {
echo "Erreur de lecture:" . socket_strerror($err) . PHP_EOL;
break;
}
} elseif ($data === '') {
// La connexion se ferme
break;
}
echo $data;
}
socket_close($socket);
Ce code montre comment utiliser socket_clear_error () pour ignorer les erreurs temporaires sans données en mode non bloquant et lire avec succès la réponse HTTP.
De cette façon, le rôle et l'utilisation de socket_clear_error () seront clairs. N'oubliez pas de nettoyer l'état d'erreur en temps opportun dans les scénarios non bloquants, longs et autres scénarios, ce qui peut rendre votre programme de socket plus robuste.