Dans PHP, lors de la programmation avec des sockets natifs, la fonction socket_accept () est utilisée pour accepter les demandes de connexion du client, mais par défaut, cette fonction bloque - c'est-à-dire s'il n'y a pas de connexion client, le programme attendra et ne peut pas automatiquement être sorti. Afin d'éviter que le programme soit coincé ou ne répond pas en raison de l'attente de la connexion, nous pouvons combiner socket_set_timeout () pour obtenir un contrôle de délai d'expiration de la connexion, améliorant ainsi la robustesse du programme.
Cet article introduira en détail comment utiliser socket_accept () et socket_set_timeout () pour implémenter la fonction du contrôle du délai de temps de connexion PHP.
socket_accept ($ socket)
En attendant le blocage de la demande de connexion client, s'il existe une demande de connexion, une nouvelle ressource de socket sera renvoyée, sinon elle sera bloquée.
socket_set_timeout ($ socket, $ secondes, $ microsecondes)
Définit l'heure du délai d'expiration de la prise spécifiée. Après le délai d'expiration, l'opération de lecture / écriture renvoie une erreur de délai d'expiration.
Il convient de noter que socket_set_timeout () est un contrôle de délai d'expiration pour les opérations de lecture et d'écriture, et ne peut pas contrôler directement le temps d'attente de blocage de socket_accept () . Par conséquent, nous devons coopérer avec d'autres moyens (tels que le mode non bloquant ou utiliser socket_select () ) pour réaliser un temps d'attente de connexion véritable.
Définissez la prise d'écoute sur le mode non bloquant <br> L'appel socket_accept () de cette manière ne bloquera pas. S'il n'y a pas de demande de connexion, FALSE sera renvoyé immédiatement.
Utilisez une boucle + retard pour juger le délai d'expiration <br> Appelez Socket_Accept () à plusieurs reprises dans la boucle. Si FALSE est retourné, déterminez si le délai d'attente est expiré. Si le délai d'attente est synchronisé, l'attente sera sortie.
Une fois la connexion reçue, utilisez socket_set_timeout () pour définir le délai de lecture et d'écriture <br> Assurez-vous qu'il y a un contrôle de temps mort lors de la transmission des données ultérieures.
<?php
$host = "0.0.0.0";
$port = 12345;
$timeoutSeconds = 10; // Temps de connexion en attente maximale
// créer TCP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create failed: " . socket_strerror(socket_last_error()) . "\n");
}
// Port de lier
if (socket_bind($socket, $host, $port) === false) {
die("socket_bind failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}
// Écouter le port
if (socket_listen($socket, 5) === false) {
die("socket_listen failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}
// Configuration de la surveillance socket Ne pas bloquer
socket_set_nonblock($socket);
$startTime = time();
$clientSocket = false;
echo "En attente de la connexion du client,Temps mort:{$timeoutSeconds}Deuxième\n";
while (true) {
$clientSocket = @socket_accept($socket);
if ($clientSocket !== false) {
echo "Le client est connecté!\n";
break;
}
// Déterminez si le délai d'attente est
if ((time() - $startTime) >= $timeoutSeconds) {
echo "En attente de la connexion du client超时。\n";
break;
}
// Dormir 100ms éviter CPU Occupation trop élevée
usleep(100000);
}
if ($clientSocket !== false) {
// Configuration du client socket Lire et rédiger le délai d'expiration,Par exemple 5 Deuxième
socket_set_option($clientSocket, SOL_SOCKET, SO_RCVTIMEO, ["sec"=>5, "usec"=>0]);
socket_set_option($clientSocket, SOL_SOCKET, SO_SNDTIMEO, ["sec"=>5, "usec"=>0]);
// Exemple de lecture des données du client
$buf = '';
$bytes = socket_recv($clientSocket, $buf, 2048, 0);
if ($bytes === false) {
echo "Échec de la réception des données ou expiré:" . socket_strerror(socket_last_error($clientSocket)) . "\n";
} else {
echo "Données du client reçu:" . $buf . "\n";
}
socket_close($clientSocket);
}
socket_close($socket);
?>
Écoute non bloquante : utilisez socket_set_nonblock () pour éviter le blocage socket_accept () , nous permettant de personnaliser la logique du délai d'attente.
La boucle pour attendre la connexion : chaque fois que socket_accept () est appelée, s'il n'y a pas de connexion, il renvoie faux immédiatement et détermine si la condition de temps mort est atteinte. Si le délai d'expiration n'expire pas, continuez d'attendre.
Définissez le délai de lecture et d'écriture après la connexion : utilisez socket_set_option () pour définir le délai d'expiration de lecture et d'écriture pour le socket client afin d'éviter le blocage permanent lorsque les données suivantes sont lues.
usleep () Réduisez l'utilisation du processeur : évitez les boucles vides provoquant une utilisation excessive du processeur.
En définissant la prise d'écoute sur le non-blocage et la combinaison du sondage en boucle pour déterminer l'heure, le contrôle du délai d'expiration de socket_accept () bloquant la connexion d'attente est obtenu. Dans le même temps, après avoir reçu la connexion, utilisez socket_set_option () pour définir le délai d'expiration de lecture et d'écriture pour assurer la stabilité et la sécurité du processus de transmission des données.
Cette solution est simple et pratique, et convient très pour les programmes de serveurs PHP qui nécessitent une gestion manuelle des délais d'attente de connexion à socket.