LLUDP ClientStack/fr
From OpenSimulator
Contents |
Introduction
Voici quelques notes au sujet de la mise en oeuvre de la pile LLUDP d'un client OpenSimulator, un bout de code utilisé pour envoyer et recevoir les paquets des viewers (clients) implémentant le protocole de l'environnement virtuel Linden Labs.
Ainsi cette pile va gérer :
- la mise en place d'une file d'attente de traitement des entrées UDP pour chaque région,
- le traitement des messages UDP entrants depuis un viewer connecté,
- la distribution des messages UDP reçus au code de traitement approprié (par exemple, le code du traitement de la sélection si une prim est sélectionnée.)
- l'envoi des messages UDP sortants vers un viewer connecté,
- le contrôle du flux des messages sortants,
- l'envoi et la réception des messages ACK(accusé de réception), aussi bien à l'intérieur d'autres messages que dans des messages autonomes,
- le renvoi de messages marqués comme fiables mais non reconnus par le viewer,
- la mutualisation des structures de la pile du client (par exemple les classes représentant les messages) pour augmenter l'efficacité et réduire la mémoire utilisée.
Commandes de console utiles
Ces commandes de console sont utiles pour déboguer ou explorer le protocole LLUDP.
- debug lludp packet [--default | --all] <level> [<avatar-first-name> <avatar-last-name>] - Active le débogage des paquets. Pour OpenSimulator 0.7.5 et antérieur, cette commande était "debug packet". "--default" applique le nouveau niveau de connexion à tous les avatars qui se sont connectés après ce point. "--all" applique ce niveau à les avatars existant.
- debug lludp pool <on|off> - active ou désactive la mutualisation des objets dans le composant lludp
- debug lludp start <in|out|all> - contrôle du traitement des paquets LLUDP
- debug lludp status -renvoie le statu du traitement des parquets LLUDP
- debug lludp stop <in|out|all> - Arrête le traitement de paquet LLUDP.
UDP entrant
Parcours du code
Partie 1
- Les messages UDP sortants sont reçus sur le port d'écoute UDP d'une région (actuellement dans OpenSimUDPBase). Ils sont passés par IOCP (input/output completion port) pendant leur traitement asynchrone.
- Quand leur réception est terminée, le thread démarre une autre réception asynchrone (qui peut être gérée par un thread IOCP différent).
- La longueur et les malformations de base sont détectés pour chaque paquet reçu.
- Les données sont insérées dans une structure de paquet en fonction d'un groupe.
- Si le paquet:
- est UseCircuitCode (utilisé pour définir les circuits avec les viewers) alors il sera traité sur un fil séparé.
- est CompleteAgentMovement (utilisé pour compléter l'insertion d'un avatar dans une région) alors il sera traité par un fil séparé.
- est un paquet normal complété par des messages ACK avec ou est un message ACK isolé, alors il sera traité.
- est fiable, alors un ACK de mise en attente est ajouté pour attendre l'acquittement du client.
- est AgentUpdate et n'est pas significatif (même chose que le dernier paquet, lorsque ceux-ci sont reçus à environ 10 fois par seconde) alors il est rejeté.
- est StartPingCheck alors il est traité.
- Tous les autres paquets sont placés dans une queue (packetInbox) pour être traités ultérieurement.
- Le fil est libéré (l'extraction synchrone n'est pas encore opérationnelle).
Partie 2
- Continuellement, un thread récupère la suite de paquets à l'avant de la file d'attente packetInbox.
- Il entre dans la structure LLClientView, pour connecter les détails du paquet à des fin de débogage si nécessaire.
- Le paquet est traité de manière synchrone (dans le même thread) ou de façon asynchrone en le plaçant dans une file d'attente d'items de travail pour d'un groupe de thread ( SmartThreadPool par défaut).
- Certains paquets sont traités de façon synchrone en raison des problèmes que cela pourrait causer s'ils étaient traités dans l'ordre (par exemple, la modification d'une texture multi-face ne pourrait pas se faire correctement). D'autres peuvent être traités de façon synchrone par défaut alors qu'il pourraient être traités de façon asynchrone.
- La longue file de threads effectue des boucles.
UDP sortant
Parcours du code
Cette section est très incomplète
- LLUDPServer.SendPacketFinal() est l'avant dernière méthode avant que les données UDP soient placées dans le fil.
- Si le paquet n'est pas un code null et qu'il a la place, alors tous les ACKs d'attente sont ajoutés.
- Si le paquet est fiable, alors le serveur enregistre son attente d'un acquittement par le client.
- S'il n'y a pas de paquet en attente d'envoi pour un contrôle et aucun dans la boîte d'envoi, alors BeginFireQueueEmpty().
- LLUDPClient.BeingFireQueueEmpty active l'événement HasUpdates pour déterminer si des mises à jour sont en attente.
- LLClientView.HandleHasUpdates() gère cela est retourne true s'il existe une file d'attente de mises à jour d'entités, des mises à jour de propriétés d'entités ou des mises à jour du gestionnaire d'image (chargement UDP d'asset).
- Si de telles mises à jour sont en attente, un thread de groupe FireQueueEmpty() est déclenché.
- Cela envoie alors l'événement OnQueueEmpty.
- LLClientView traite avec HandleQueueEmpty() qui va placer un certain nombre de mises à jour via OutPacket.
Contrôles
Il existe aussi une ancienne discussion informelle au sujet du contrôle par étranglement, Sim Throttles, qui peut ou ne peut pas être exacte. Le flux des messages UDP sortants sont contrôlés (étranglés) par le client avec un contrôle optionnel pour la scène dans son entier.
Configuration
Si
[ClientStack.LindenUDP] enable_adaptive_throttles = true
(par défaut). Alors le contrôle du flux vers le client est ajusté automatiquement par le serveur. Lorsque la connexion est bonne, la performance est augmentée. Toutefois, si les paquets marqués comme fiables ne sont pas reçus en temps opportun, les arrivées sont réduites pour qu'aucun paquet ne soit perdu. La manette des gaz est ensuite progressivement augmentée jusqu'à revenir à son état initial ou que trop de paquets soient perdus.
Si
[ClientStack.LindenUDP] enable_adaptive_throttles = false
Le contrôles est défini par le client.
En fonction de l'adaptation ou la configuration du contrôle par le client, le taux d'étranglement peut encore être limité côté serveur en définissant un ou deux des paramètres ci-dessous
[ClientStack.LindenUDP] client_throttle_max_bps = <some-client-limit> scene_throttle_max_bps = <some-entire-scene-limit>
Le paramètre client_throttle_max_bps va imposer une limite maximum pour chaque connexion du client. Le paramètre scene_throttle_max_bps va définir une limite maximale des sorties pour toutes les connexions à la scène. Aussi pour cette dernière limite, chaque connexion supplémentaire va réduire la bande passante pour tout le monde à une limite fixe et la partager entre plusieurs clients. Cela inclut les connexions enfants (utilisées par les clients pour les avatars des régions voisines qui observent l'activité de la région.)
Aucune de ces limites n'est définie par défaut.
Autres références
- Sim Throttles fait mention d'informations très anciennes au sujet de l'implémentation de l'étranglement. Cela a changé considérablement depuis, mais ce document peut être encore utile.