Jump to content
Sign in to follow this  
v4vx

Système de Socket

Recommended Posts

Niveau requis Débutant

Temps estimé : 60 minutes

Salut à tous,

 

certains d'entre vous ont peut-être envi de faire un émulateur, mais vous n'avez pas certaines compétences pour en faire un de A à Z... Eh bien me voilà pour vous donner l'outil de base : le système de socket !

 

I - Définitions et première approche

 

Révélation

 

A - Définitions

 

Révélation

 

Le socket est ce qui permet de communiquer entre deux programmes, par le réseau. En gros c'est ce qui fait la connexion.

Dans le cas d'un émulateur, avoir un bon système de socket est très important, car c'est lui qui capte toute les actions envoyé par le client sous forme de packets.

 

Un packets est une requête, ou un morceau de requête envoyé par un programme (via un socket), et reçut par un autre (via un socket aussi). Les packets sont des tableaux d'octets, contenant la plupart du temps, une fois analysé et complet, un texte. Par exemple :


AlEf
C'est un packet envoyé par un serveur Dofus, permettant de dire au client que la connexion à échoué. En gros les packets est ce qui transite entre chaque sockets, pour pouvoir faire tel ou tel action.

 

 

B - Utilisation

 

Révélation

 

Le système de socket sur un serveur doit être constituer de plusieurs parties.

 

  1. Le serveur, qui accepte les connexions
  2. La réception des packets (et analyse)
  3. L'envois des packets

 

Chaque connexions doivent être séparés, pour éviter que l'une bloque l'autre en recevant les données, ou en écrivant.

Le serveur doit lui aussi être séparé, pour qu'il puisse toujours accepter de nouvelles connexions.

 

Pour éviter qu'une opération bloque tout le reste du programme, quelque chose a été inventé : les Threads.

Les Threads sont en quelque sorte des sous-parties du programmes, s'exécutant en parallèle. Donc si un tread est bloqué, tout le reste peut continuer à fonctionner sans problème.

 

Donc à première idée, l'on crée un thread pour le serveur, puis à chaque nouvelles connexions, un autre thead pour éviter de bloquer les autres quand l'on reçoit ou que l'on veut envoyer des packets.

 

 

C - Limites de ce système

 

Révélation

 

Mais ce système, utilisé par Ancestra (la réfénrence de ce qui ne faut pas faire x) ) comporte quelques lacunes. Pour commencer, il faut savoir que en réalité les tâches des threads ne s'exécutent pas totalement en parallèle, mais sont géré par (chez java) la JVM. Bon on, peut me dire Quel est le problème ?, Hé bien, les threads sont enfaite tout le temps activés et désactivés pour que les autres puissent s'activer et fonctionner.

 

Tout cela est du au fait que le processeur ne pas en théorie exécuter plusieurs tâches en même temps. En théorie, car dans la réalité, le processeur contient généralement, de nos jours, au moins 2 cœurs, souvent 4, qui sont en plus couplé par certaines technologies comme Hyper-Threading de intel, qui double de façon virtuel le nombre de cœurs.

Donc d'origine, le CPU à en moyenne 4 threads physique (ou semi-physique avec l'Hyper-Threading). (Chez moi j'en suis à deux x') ).

 

Pour revenir au sujet, au maximum 4 tâches (sur un pc moyen, si vous avez un i7, sa en fait 8, et un intel Xeon octocores, 16) qui fonctionnes réellement en parallèles, et partagé par les 10 000 processus tournant sur votre PC, dont 100 qui sont prioritaires. Vos thread java seront donc continuellement désactivés. Mais leur activation est géré de manière anarchique par JVM. Il se peut donc qu'un joueur AFK ai sont thread souvent sollicité, alors qu'un joueur en combat, lui l'est beaucoup moins. Le premiers arrivés ne sont pas forcément les premiers servis.

 

De plus l'activation et la désactivation d'un thread prend du temps (et de la puissance), et plus il y a de threads, plus il faut partager se temps précieux entre chacun, et au final perdre du temps à activer/désactiver. Si beaucoup de clients sont connectés, la puissance sera non pas utilisé par le jeu lui même, mais par le JVM pour gérer ses threads. Ce système n'est donc pas conseillé sur un gros serveur.

 

Ensuite, qui dit thread, dit objet (en java tout est objet de tout façon...), et dit aussi mémoire. Donc plus il y a de clients, plus il y a utilisation de mémoire inutile.

 

Enfin, les threads utilisant des sockets inactifs utilisent autant de mémoire, de temps et de puissance que tout les autres, mais inutilement. L'idéal serait de ne pas dépasser 10 Threads par cœurs physiques, ou virtuelles.

 

 

 

II - Un autre système : La théorie

 

Révélation

 

A - Explications

 

Révélation

 

Ce système serait d'utiliser un nombre fixe des threads, pour éviter les problèmes rencontrés plus haut.

Pour éviter tout blocages, il faut séparer différentes étapes, en différents Threads.

 

  • Le serveur d'entrés, pour recevoir les connexions, et les packets
  • L'analyse des packets reçut
  • La sortie

 

J'ai séparé l'analyse des packets du reste, car certains packets demandent un accès à la bdd, ou a des gros calcules.

Si l'analyse se ferait directement sur le thread d'entrés, elle bloquerais les autres connexions, car l'analyse est très lourde.

La sortie est écarté des entrés, car elle est relativement lente aussi.

 

Au final 3 threads tourneront par serveurs.

Il est possible de mettre l'analyseur de packet en commun pour deux serveurs différents, je penses par exemple dans un ému Dofus, avec le Realm et le Game dans le même programme, autant mettre un gestionnaire de packet commun, pour éviter d'avoir deux fois le même code, ou d'ajouter un thread en plus.

 

 

B - Les outils

 

Révélation

 

Bon c'est bien beau tout ça, mais encore il nous faut les bons outils pour le faire... Et cet outils et la library NIO de java !

 

NIO veut dire New Input / Output. C'est un système de gestion des entrés / sorties (sans blagues ?), qui se base sur des buffers. Bon, passons plutôt à ce qui nous intéresse...

 

NIO propose un système de socket non-bloquant, c'est à dire qui n'attendent pas (et bloque le thread) pour recevoir un packet par exemple. Les packets sont gérés de façon Asynchrone.

Uniquement les packets prêts à recevoir ou écrire sont utilisés, les autres sont passés. Cela résout un problème vu précédemment, où les thread inactifs ont la même priorité que les inactifs.

 

Mais ça ne s'arrête pas que là. Ils nous mettent aussi à notre disposition des sélecteurs, qui permettent de sélectionner UNIQUEMENT les sockets prêts aux transferts, évitant d'avoir un boucle parcourant tout les sockets, même les inactifs (et une perte de puissance).

 

 

 

Cordialement,

Hey hey

Share this post


Link to post

Bonsoir,

Malgré le fait que je n'ai même pas les bases en Java j'ai plus ou moins compris ton petit cours..

Je trouve que tu rédige de façon propre et lisible donc ça facilite la compréhension.

J'attends la suite avec impatience :P

 

Cordialement,

KaynabX

Share this post


Link to post

Bonsoir,

Malgré le fait que je n'ai même pas les bases en Java j'ai plus ou moins compris ton petit cours..

Je trouve que tu rédige de façon propre et lisible donc ça facilite la compréhension.

J'attends la suite avec impatience :P

 

Cordialement,

KaynabX

 

Merci :)

 

(enfin une réponse lol)

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.