Lors de la rédaction d'applications de serveur basées sur des socket à l'aide de PHP, socket_accept () est une fonction clé pour recevoir des connexions client. Cependant, dans certains scénarios, même si la logique du programme est correcte, socket_accept () peut ne pas recevoir la connexion normalement. Cet article expliquera comment utiliser les outils Strace et Netstat pour localiser et résoudre rapidement ce problème.
Ce qui suit est un simple programme de serveur PHP qui écoute le port 8080:
<?php
$host = '0.0.0.0';
$port = 8080;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket);
echo "Server listening on $host:$port\n";
while (true) {
$client = socket_accept($socket);
if ($client === false) {
echo "Failed to accept connection\n";
continue;
}
$msg = "Hello from server\n";
socket_write($client, $msg, strlen($msg));
socket_close($client);
}
?>
Lorsque vous trouvez socket_accept () bloqué ou toujours renver false , vous devez utiliser des outils système pour effectuer un dépannage approfondi.
Strace est un outil de suivi des appels système sous Linux. Vous pouvez afficher directement les fonctions sous-jacentes du système sous-jacentes par les scripts PHP à l'exécution et leurs résultats d'exécution.
Trouvez le PHP Process Pid qui s'exécute, par exemple en utilisant PS :
ps aux | grep php
Utilisez Strace pour se fixer au processus:
strace -p <PID> -e trace=network
Observez si le comportement suivant existe dans la sortie:
accepter (...) = -1 : l'échec de l'appel du système, généralement accompagné de codes d'erreur (comme Eagain , Econnaborted , etc.)
Écoutez (...) ou liez (...) Erreur: peut signifier que le port est occupé ou que les autorisations sont insuffisantes
Pas d'appel à accepter () : le programme peut être bloqué ailleurs
Si Strace montre accepter () est normal mais n'a toujours pas d'accès à la connexion, le problème peut être dans la couche réseau ou le pare-feu.
Netstat et SS peuvent être utilisés pour vérifier si le port est à l'état d'écoute et s'il y a une connexion établie.
netstat -tlnp | grep :8080
ou:
ss -tlnp | grep :8080
Vous devriez être en mesure de voir des sorties similaires à ce qui suit:
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("php",pid=12345,fd=3))
S'il n'y a pas d'écoute, socket_bind () ou socket_listten () échoue;
Si l'écoute est normale mais qu'il n'y a pas de connexion, il se peut que le client n'ait pas initié la connexion ou soit intercepté par le pare-feu;
Si le statut est CLOSID_WAIT ou TIME_WAIT , cela signifie que le cycle de vie de connexion se termine anormalement.
Vérifiez le message d'erreur <br> Après chaque appel de socket, utilisez socket_streror (socket_last_error ()) pour afficher les informations d'erreur spécifiques.
LIMITATIONS DE FIRWAL ou SELINUX <br> Utilisez des iptables ou du Firewalld pour confirmer que le port 8080 n'est pas bloqué.
Le port est occupé par d'autres programmes <br> Utilisez LSOF -I: 8080 pour vérifier si d'autres programmes occupent le port.