Lors de la création de services de réseau PHP haute performance, le mode de communication de socket de blocage traditionnel ne peut souvent pas répondre aux besoins des scénarios à haut niveau. Afin de mieux améliorer la vitesse de réponse et les capacités de débit des applications de réseau PHP, l'utilisation de socket_accept () avec socket_set_nonblock () pour obtenir une communication non bloquante est un moyen faisable et efficace. Cet article expliquera en profondeur la mise en œuvre de cette technologie et fournira un exemple de code de référence.
Par défaut, la communication PHP Socket est bloquée, c'est-à-dire lorsque le programme exécute les opérations socket_accept () ou socket_read () , s'il n'y a pas de connexion ou de données client à lire, le programme attendra. Bien que cette méthode soit simple, elle limitera considérablement la capacité de concurrence du programme.
La communication non bloquante nous permet de continuer à exécuter d'autres parties du programme sans connexion ou données client, plutôt que d'attendre tout le temps. Ce mécanisme est très adapté à la gestion des scénarios où un grand nombre de connexions courtes ou de plusieurs demandes de clients sont reçues simultanément.
socket_accept () : utilisé pour accepter les connexions du client. S'il n'y a pas de connexion, il bloquera jusqu'à ce qu'une connexion arrive à venir.
socket_set_nonblock () : définir la prise en mode non bloquant afin que socket_accept () ne bloque pas le thread principal en raison de aucune connexion.
En mode non bloquant, nous pouvons écouter de nouvelles demandes de connexion en boucle par boucle sans bloquer l'intégralité du processus en raison d'une connexion non engagée. Nous pouvons combiner socket_select () pour interroger l'état de plusieurs prises pour optimiser davantage les performances.
Voici un exemple de serveur PHP simple utilisant une prise non bloquante:
<?php
$host = '0.0.0.0';
$port = 8080;
// créersocket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($server === false) {
die("socket_create() failed: " . socket_strerror(socket_last_error()));
}
// installationsocketPour réutilisable
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
// Port de lier
if (!socket_bind($server, $host, $port)) {
die("socket_bind() failed: " . socket_strerror(socket_last_error($server)));
}
// moniteur
if (!socket_listen($server, 5)) {
die("socket_listen() failed: " . socket_strerror(socket_last_error($server)));
}
// installation为Non bloquant
socket_set_nonblock($server);
$clients = [];
echo "Le serveur est démarré,moniteur端口 $port ...\n";
while (true) {
// Acceptez de nouvelles connexions(Non bloquant)
$client = @socket_accept($server);
if ($client !== false) {
socket_set_nonblock($client);
$clients[] = $client;
echo "NOUVEAU CONNEXION CLIENT: " . count($clients) . " Nombre total de connexions\n";
}
// Traiter les données des clients
foreach ($clients as $key => $client) {
$data = @socket_read($client, 1024, PHP_NORMAL_READ);
if ($data === false) {
continue;
}
if ($data === "") {
// Déconnexion du client
socket_close($client);
unset($clients[$key]);
echo "Déconnexion du client\n";
continue;
}
$data = trim($data);
if ($data) {
echo "Données reçues: $data\n";
$response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello from m66.net\r\n";
socket_write($client, $response);
socket_close($client);
unset($clients[$key]);
}
}
// éviterCPUOccupation100%
usleep(100000);
}
socket_close($server);
?>
Les principaux avantages de l'utilisation de socket_set_nonblock () sont:
Il ne bloque pas le thread principal, permettant de traiter plusieurs connexions simultanément;
Facile à combiner avec des fonctions telles que socket_select () pour implémenter des boucles d'événements plus complexes;
Il peut améliorer les performances dans des scénarios de concurrence élevés, tels que les salles de chat, la messagerie instantanée, les serveurs WebSocket, etc.
En mode non bloquant, vous devez faire attention à la gestion des exceptions, comme utiliser @ pour supprimer les erreurs ou pour juger socket_last_error () .
Dans la logique du code, il est nécessaire de gérer activement le cycle de vie de la connexion pour éviter la fuite des ressources.
Pour un contrôle de concurrence complexe, vous pouvez envisager de combiner plusieurs processus (tels que pcntl_fork () ) ou à l'aide de cadres Coroutine (tels que Swoole).
En combinant socket_accept () avec socket_set_nonblock () , nous pouvons améliorer efficacement les performances et la vitesse de réponse de la concurrence des applications de réseau PHP. Bien que PHP ne soit pas aussi puissant que certains langages sous-jacents de la programmation réseau, il peut toujours créer un système de service réseau stable et fiable de manière raisonnable. J'espère que cet article vous aidera à comprendre le mécanisme de communication non bloquant et sa pratique.