Lorsque vous utilisez des sockets pour la programmation réseau en PHP, le mode non bloquant peut améliorer les capacités de traitement simultanées et est la clé pour implémenter des serveurs pilotés ou multiplexés sur des événements. Cependant, nous devons parfois définir temporairement la prise sur le blocage de l'état pour effectuer certaines opérations "doivent attendre", telles que la lecture d'un grand paquet de données dans son intégralité, ou en attendant que le client envoie des données complètes de poignée de main.
Heureusement, PHP fournit deux fonctions: socket_set_block () et socket_set_nonblock () , qui peut facilement basculer entre les modes de blocage et non bloquant.
Cet article combinera un exemple de serveur TCP spécifique pour montrer comment changer temporairement la prise à un état de blocage dans l'écoute non bloquant et restaurer l'état non bloquant après avoir terminé l'opération.
Nous créons un serveur TCP non bloquant, écoutons la connexion client, et après avoir reçu la connexion client, nous passons temporairement la connexion en mode de blocage, lisons un élément de données du client, puis passons en mode non bloquant une fois terminé.
Voici le code complet:
<code> <? Php $ host = '0.0.0.0';
$ port = 12345;
// Créer une prise
$ server = socket_create (af_inet, sock_stream, sol_tcp);
socket_set_option ($ serveur, sol_socket, SO_ReUSEADDR, 1);
// Liaison et écoute
socket_bind ($ server, $ host, $ port);
socket_Listeten ($ serveur);
// réglé sur non bloquant
socket_set_nonblock ($ serveur);
echo "Server écoutant sur {$ host}: {$ port} ... \ n";
$ clients = [];
while (true) {
// Accepter la connexion (non bloquant)
$ client = @socket_accept ($ serveur);
if ($ client! == false) {
echo "Nouveau client connecté. \ n";
// Ajouter à la liste des clients
$ clients [] = $ client;
// Définissez le client sur le non-bloquant
socket_set_nonblock($client);
}
foreach ($clients as $index => $sock) {
$buffer = '';
// Temporairement réglé sur bloquer pour assurer la lecture complète(Par exemple, lisez une longueur fixe ou jusqu'à un drapeau)
socket_set_block($sock);
$bytes = @socket_recv($sock, $buffer, 1024, MSG_DONTWAIT);
// Revenir à la non-blocage
socket_set_nonblock($sock);
if ($bytes === false || $bytes === 0) {
// Client déconnecté
echo "Client disconnected.\n";
socket_close($sock);
unset($clients[$index]);
continue;
}
// Données de lecture de sortie
echo "Received: " . trim($buffer) . "\n";
// Échantillon de réponse
$response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from server!\n";
socket_write($sock, $response);
}
// Un léger retard d'évitement CPU Complet
usleep(100000);
}
socket_close ($ serveur);
?>
</code>
Dans le code ci-dessus, notre socket d'écoute ($ serveur) est non bloquante et ne bloque donc pas sur socket_accept () . Chaque fois qu'une nouvelle connexion est acceptée, nous définissons également le nouveau client sur le non-blocage. Cependant, dans la partie où nous traitons les données de réception, nous passons activement la prise du client en mode de blocage, car nous voulons nous assurer que socket_recv () peut recevoir pleinement les données que nous attendons et éviter l'incomplétude des données.
Il s'agit d'une méthode d'utilisation mixte très courante et est particulièrement importante dans de nombreux scénarios (comme la phase de poignée de main du protocole). Par exemple, vous avez conçu un protocole simple qui stipule que le client doit contenir des informations d'en-tête fixe pour la première fois, et le serveur doit le recevoir complètement avant de pouvoir continuer le traitement. À l'heure actuelle, l'utilisation de lecture de blocage devient très significative.
Soyez prudent lors de la commutation des modes : utiliser temporairement la lecture de lecture dans des processus non bloquants est une méthode "d'attente forcée". Bien que cela soit pratique, si le client n'envoie aucune donnée, le serveur sera bloqué. Il est recommandé de correspondre au mécanisme de temps mort ou à la longueur des données prédéfinies.
Convient pour le blocage à court terme : ce type de commutation de mode convient aux situations où certaines opérations doivent être bloquées et il n'est pas recommandé d'utiliser le blocage tout au long du processus de communication.
Utilisez socket_set_block () et socket_set_nonblock () pour rendre votre programmation de socket PHP plus flexible. Vous pouvez sélectionner de manière flexible le mode de blocage approprié en fonction de la logique de traitement, prenant ainsi en compte l'efficacité et l'intégrité.
Pour plus de pratiques et d'exemples de programmation de socket, veuillez vous référer à la documentation ou visiter notre plateforme de ressources: