coimdavid | Bonjour j utilise le moteur php pour créer un petit programme pouvant recevoir des socket exterieur,
jusqu a la tout va bien, il me renvoi bien la donnée sur le client l'envoyant;
Mon besoin étant de renvoyer toutes les informations issus de n'importe quels clients vers tout les utilisateurs connectés.
exemple 3 CX en simultanées, un d'une des connexions envoie "1", les trois connection devront recevoir le "1" envoyé par la connection.
Merci de de votre aide
Code :
- <?php
- // On se replace dans le répertoire où est stocké le script
- chdir(dirname(__FILE__));
- // On initialise un tableau contenant la liste des sockets à surveiller
- $watchSockets = array();
- // On initialise un tableau contenant les sockets clients
- $clients = array();
- // On initlialise un tableau contenant les sockets threads
- $threads = array();
- // On initialise un tableau contenant les données temporaires à envoyer à un nouveau thread
- $threadsTemp = array();
- // -----------------------------------
- // On crée la socket "externe"
- $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
- // On la lie, ici sur le port 10000
- socket_bind($socket, '0.0.0.0', 10000);
- // On la fait écouter
- socket_listen($socket, 5);
- // On ajoute la socket du serveur dans la liste des sockets à surveiller (pour les nouvelles connexions)
- $watchSockets[] = $socket;
- // -----------------------------------
- // On crée la socket "interne" pour la communication avec les threads
- $threadSocket = socket_create(AF_UNIX, SOCK_STREAM, NULL);
- // On la lie, ici sur la socket /tmp/monserveur.socket
- socket_bind($threadSocket, '/tmp/monserveur.socket');
- // On la fait écouter
- socket_listen($threadSocket);
- // On ajoute la socket du serveur interne dans la liste des sockets à surveiller (pour les nouveaux threads)
- $watchSockets[] = $threadSocket;
- // Boucle infinie
- while (TRUE)
- {
- // Surveillance des sockets en attente de données à lire
- // Si pas de données à lire : on relance la boucle
- $toRead = $watchSockets; // Parce que socket_select() modifie le tableau passé en paramètre et que l'on veut garder notre variable $watchSockets
- if (!@socket_select($toRead, $write = NULL, $except = NULL, 0)) continue;
- // Il y a des données à lire
- // Le socket d'écoute éxtérieur a-t-il reçu des données ?
- if (in_array($socket, $toRead))
- {
- // Oui : il s'agit d'une nouvelle connexion
- // Acceptons-la
- $newConnection = socket_accept($socket);
- // Ajoutons-la à la liste des clients
- $clients[] = $newConnection;
- // Ajoutons-la à la liste des sockets à surveiller
- $watchSockets[] = $newConnection;
- // Créons un thread qui s'occupera de ce client
- // ATTENTION : vérifiez que le chemin vers PHP est correct
- // On passe en outre l'ID du client dans le tableau de correspondance pour que l'on puisse identifier le thread lors de sa connexion plus tard
- // Les caractères étranges de la fin de la commande assurent l'éxécution en arrière-plan
- exec('/usr/local/bin/php thread.php '.strval(count($clients) - 1).' 2>/dev/null >&- <&- >/dev/null &');
- // Supprimons la socket d'écoute de la liste des sockets à lire
- // (pour éviter d'interférer avec la suite)
- $key = array_search($socket, $toRead);
- unset($toRead[$key]);
- }
- // Le socket d'écoute interne (threads) a-t-il reçu des données ?
- if (in_array($threadSocket, $toRead))
- {
- // Oui : un thread est prêt et tente de se connecter
- // Acceptons la connexion
- $newConnection = socket_accept($threadSocket);
- // Récupérons l'ID du thread
- $data = socket_read($newConnection, 4, PHP_BINARY_READ);
- var_dump($data);
- $id = unpack('lid', $data); $id = $id['id'];
- // NOTE : cette méthode n'est en théorie pas optimale au niveau perfs, socket_read() pouvant bloquer un court instant
- // Pour éviter cela, il faut récupérer l'ID en surveillant le socket (en attendant il faut placer le socket client dans une pile temporaire)
- // Cette dernière variante n'est pas utilisée ici pour ne pas compliquer le code mais ne présente pas de difficulté majeure
- // Ajoutons-la à la liste des threads
- $threads[$id] = $newConnection;
- // Ajoutons-la à la liste des sockets à surveiller
- $watchSockets[] = $newConnection;
- // A-t-on des données à lui passer, qui ont été stockées temporairement ?
- if (strlen($threadsTemp[$id]))
- {
- // Oui : passons les
- for ($writed = 0; $writed < strlen($threadsTemp[$id]); $writed += socket_write($newConnection, substr($threadsTemp[$id], $writed)));
- unset($threadsTemp[$id]);
- }
- // Supprimons la socket d'écoute de la liste des sockets à lire
- // (pour éviter d'interférer avec la suite)
- $key = array_search($threadSocket, $toRead);
- unset($toRead[$key]);
- }
- // Parcourons la liste des sockets clients et threads ayant reçu des données
- foreach ($toRead as $oneSocket)
- {
- if (in_array($oneSocket, $clients))
- {
- // Il s'agit d'un client externe
- // Client >> SCRIPT >> thread
- // Obtenons l'ID client correspondant
- $key = array_search($oneSocket, $clients);
- // Lisons la socket sur disons... 1024 octets
- // (un choix purement arbitraire, peut néanmoins influer sur les performances, pensez à faire des tests)
- $data = socket_read($oneSocket, 1024);
- if (!strlen($data))
- {
- // La connexion avec le client s'est interrompue
- // Fermons le socket client
- socket_close($oneSocket);
- // Fermons le socket thread
- @socket_close($threads[$key]);
- // On coupe tout
- unset($clients[$key]);
- unset($threads[$key]);
- $watchKey = array_search($oneSocket, $watchSockets);
- unset($watchSockets[$watchKey]);
- }
- else
- {
- // Le thread associé est-il prêt et connecté ?
- if (isset($threads[$key]))
- {
- // Oui : passons lui les données
- for ($writed = 0; $writed < strlen($data); $writed += socket_write($threads[$key], substr($data, $writed)));
- }
- else
- {
- // Non : on les stocke temporairement
- $threadsTemp[$key] .= $data;
- }
- }
- }
- elseif (in_array($oneSocket, $threads))
- {
- // Il s'agit d'un thread
- // Thread >> SCRIPT >> client
- // Obtenons l'ID du thread correspondant
- $key = array_search($oneSocket, $threads);
- // Lisons la socket sur disons... 1024 octets
- // (un choix purement arbitraire, peut néanmoins influer sur les performances, pensez à faire des tests)
- $data = socket_read($oneSocket, 1024);
- if (!strlen($data))
- {
- // La connexion avec le thread s'est interrompue (autrement dit, il veut fermer la connexion avec le client)
- // Fermons le socket client
- socket_close($clients[$key]);
- // Fermons le socket thread
- socket_close($oneSocket);
- // On coupe tout
- unset($clients[$key]);
- unset($threads[$key]);
- $watchKey = array_search($oneSocket, $watchSockets);
- unset($watchSockets[$watchKey]);
- }
- else
- {
- // Passons les données au client correspondant
- for ($writed = 0; $writed < strlen($data); $writed += socket_write($clients[$key], substr($data, $writed)));
- }
- }
- }
- }
- ?>
|
|