IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau et multijoueurs Discussion :

Deamon d'un MMORPG


Sujet :

Réseau et multijoueurs

  1. #1
    Futur Membre du Club
    Inscrit en
    Décembre 2010
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Deamon d'un MMORPG
    Bonjour à tous et à toutes

    Je suis actuellement (enfin dans mes temps libres) en train de développer un jeu MMORPG.

    Je vous arrête tout de suite! Je ne fais pas un MMORPG ultra compliqué comme wow, flyff, rappelz, ou tout ce que vous voulez. Je fais un projet moyennement complexe et en version simplifiée pour commencer (ma première version fonctionnelle consiste uniquement à gérer la connexion des utilisateurs ainsi que leurs déplacements).

    Bon, donc pour en venir à ma question, j'aimerais que quelqu'un m'explique le fonctionnement d'un deamon.

    J'ai déjà cherché ailleurs, mais personne n'a su me donner une réponse précise.

    Comment dois-je diviser les tâches dedans ?
    Suis-je sensé créer un cahier des charges juste pour le serveur ? lister tout ce qu'il doit faire, puis séparer ça en module ?

    Voici la meilleure réponse que j'ai eu sur ce sujet :

    J'ai aussi déjà fais des recherches là dessus, et globalement on peut lire que 1t/client ça donne tout de suite beaucoup de threads et qu'on perd alors de l’efficacité, mais que 1t/tâche permet d'avoir une bonne moyenne : Tu peut prendre par exemple :
    Thread 1: Base de donnée;
    Thread 2: Logs;
    Thread 3: Connecter/Déconnecter les client;
    Thread 4: Recevoir les données;
    Thread 5: Envoyer les données;
    Thread 6: Gérer le monde ou la map/carte;
    Est-ce une bonne chose ? avez-vous une meilleure solution ? est-ce que ces modules doivent tous communiquer par message ou ils devraient tous avoir un pointeur sur les autres afin de faire des appels directs de méthode ?

    (parce que sur mon client, je fonctionne : Engine est maître, Sound, Network, Graphics, Event sont d'autres modules simplement. Chaque module tourne dans un thread et fais ce qu'il doit faire. Ils communiquent tous en appels direct excepté Network, qui envoie les messages reçus sosu forme de structure à engine, pour qu'il puisse les traiter. mais plus j'y pense, plus je me demande si je devrais pas "inclure" Engine dans Network...)

    Merci et bonne journée

  2. #2
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 378
    Points
    20 378
    Par défaut
    Salut je ne vois pas d' améliorations particulières à apporter...
    Peut-être qu'au début tu peux fusionner des traitements dans un thread ..
    il ne faut pas perdre de vue que si tu géres des threads pour des taches distinctes, le problème majeur sera de communiquer les données entre ces threads ce qui complexifie les choses.
    Sans compter les problèmes de synchro.
    Le thread pour les logs on peut s'en passer...
    si tu as une erreur il suffit décrire dans un fichier...
    sinon quelle technologie,langage utilises-tu ?
    Est-ce que tu fais du client-serveur, une appli serveur et plusieurs clients ?
    Citation Envoyé par Neo007 Voir le message
    Bonjour à tous et à toutes

    Bon, donc pour en venir à ma question, j'aimerais que quelqu'un m'explique le fonctionnement d'un deamon.
    qu'appelles-tu un daemon ?
    Un Daemon sous Linux c'est un service sous Windows; ce sont des programmes qui tournent sans arrêt et qui sont démarrés ou non au démarrage de l'OS.
    Mais ils sont une couche en-dessous de la couche applicative c.a.d. les programmes utilisateurs..
    Il est évident que si tu fais une appli serveur qui gère des connections clientes et écoutent des sockets tu seras contraint préférablement de faire un daemon.
    Mais avant de compliquer les choses tu peux faire un simple programme exécutable serveur et tu le fais démarrer automatiquement au lancement de l'OS ( Linux,Windows...).
    Par exemple sous Windows tu peux faire une application server.exe et le mettre dans le menu "démarrer".
    Il sera lancé en même temps que Windows.

    Citation Envoyé par Neo007 Voir le message
    Bonjour à tous et à toutes
    Suis-je sensé créer un cahier des charges juste pour le serveur ? lister tout ce qu'il doit faire, puis séparer ça en module ?
    je ne suis pas partisan des documents sur plusieurs pages mais c'est préférable oui.
    Du moins c'est préférable de formaliser l'architecture sur papier puis faire un document texte au besoin.
    Tu peux faire aussi une conception des classes avec UML au besoin..
    parce qu'une architecture client-serveur ça devient vite complexe...

  3. #3
    Futur Membre du Club
    Inscrit en
    Décembre 2010
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Merci en premier pour ta reponse

    Bon, premierement, ce que j appelle un deamon, pour moi, c est une application servant a gerer quelque chose de gros et normalement assez complexe (ici je arle d une application pour gerer des joueurs sur morpg)

    Pour ce qui est des techno/lib/compilateur utilise, je code en C++ avec winsock + (client) irrlicht pour le moteur de rendu 3D, Blender pour les modelisations, libmysql pour les connexions au BDD, winsock pour les connexions de sockets et j utilise code::blocks.

    Donc, les logs, on les ote (donc 5 threads pour le serveur)

    En ce qui concerne le client que j ai commence a developper, je fais surtout de l extrem programming

    Mais j evite de parler du client puisque je n ai actuellement aucun probleme avec.

    Donc la je suis chez quelqu un, mais quand j vais revenir chez moi, j vais essayer de commencer a le developper.

    P.S. desole pour les accents et les apostrophes (lavier anglais)

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    (avant-propos : je dis une thread. Je sais très bien qu'on dit un thread - traduction : un fil. D'où le masculin. Mais je n'arrive jamais à le dire. Une mauvaise habitude est quand même une habitude )

    Je vais commencer par un peu de vocabulaire technique, et après on y va

    daemon : ce qui est bien avec ce mot, c'est qu'il frappe l'imagination. On se dit que c'est forcément gros, que c'est étrange, et que ça doit faire des choses exceptionnelle. Et bon non. La définition d'un daemon est plus simple : c'est un programme qui tourne en tâche de fond et qui est désolidarisé de toute console. On ne peut donc pas le manipuler par un clavier, pas plus qu'il ne peut afficher quoi que ce soit à l'écran. Ce n'est pas plus compliqué que ça. Sous Unix, la technique pour créer un serveur consiste à forker le programme principal et à fermer les I/O console. Sous Windows, on implémente un service (qui n'est pas strictement équivalent à un programme normal).

    serveur : là, c'est simple : c'est un programme qui sert des données à d'autres programmes. Bien évidemment, ça demande une forme ou un autre de connection, si bien qu'on parle généralement de serveur pour décrire un programme acceptant des connections entrantes via la pile réseau IP (serveur TCP en mode connecté, UDP en mode non connecté. Le mode TCP est préférable pour un MMO).

    Pour faire ton serveur de MMO, tu n'as pas besoin d'en faire un daemon. C'est tout à fait possible, bien sûr - et on peut argumenter sur le fait que ça soit même une bonne chose dès lors qu'on rentre en production. Mais on peut tout a fait imaginer un serveur en mode applicatif normal, encore attaché à une console pour qu'il puisse y faire ses sorties debug. Dans un premier temps, il est conseillé de développer son serveur sous la forme d'un programme normal. On fait en sorte que main() n'appelle qu'un nombre très réduit de fonctions, ce qui permet ensuite de modifier le programme une fois qu'il fonctionne de manière satisfaisante pour en faire un daemon ou un service.

    Maintenant qu'on a mis ça au point, on va réflechir sur ce que fait un serveur de MMO :

    1) il gère l'authentification des joueurs - c'est une partie difficile à implémenter, notamment sur les gros MMO qui acceptent beaucoup de joueurs. L'authentification est souvent déportée dans un autre programme serveur, ce qui permet d'implémenter des techniques de délestage, etc. Une fois un joueur authentifié, sa session débute. Il y a donc quelque part une gestion des sessions actives.

    2) il réponds aux requêtes envoyées par le client. Ces requêtes sont nombreuses et diverses : "met ça dans tel sac", "est-ce que mon coup touche ma cible", "puis-je parler à untel", etc. Là, bien évidemment, on commence à manipuler des tas de données.

    3) il envoie des informations au client - c'est différent du cas précédent, parce que le client ne demande rien. "tu prends X points de dégats", "il y a une mine de Zirtonosphium a tel endroit", "tu reçois un message de untel", etc. Ce processus étant indépendant de ce que demande le client, on commence à voire poindre une notion de tâche séparée.

    4) il assure certaines tâches de maintenance : gestion de la base de données, récupérations de métriques (utiles pour d'une part éviter les hack et d'autre part obtenir des informations sur ce que font les joueurs et sur ce qu'ils aiment), écriture d'informations de debug, etc.

    Bien. Comment mettre tout ça en thread ? Reprenons ton découpage.

    * Thread 3: Connecter/Déconnecter les client ; c'est une possibilité intéressante. Si la thread a une priorité correcte, ça limite le temps d'attente des clients au moment de la connection. On valide.

    * Thread 6: Gérer le monde ou la map/carte; ; de part mon point n°3, c'est presque évident : le monde est géré à part. Mais ce n'est pas suffisant dans bien des situations. On va voir ça après.

    Pour le reste, avoir deux threads pour la réception et l'envoi des données est une mauvaise chose. L'envoi de donnée est certes décoléré de la réception, mais pas à ce point. C'est lié au point précédent, que je traite à la fin de ce message.

    Une thread pour la base de données ? Non : une couche très légère qui communique avec le processus qui gère la base de donnée. C'est beaucoup plus sain. On se connecte à une base, et on lui envoie des requêtes. L'envoi d'une requête est sa réception peuvent être asynchrone (afin d'éviter les attentes). Sous Windows, on peut implémenter ce système en utilisant les fonction I/O asynchrones (overlapped I/O ; article général sur WIkipedia), plutôt que des fonctions bloquantes. Le principe est simple (mais difficile à implémenter sans le support de l'OS) : on envoie une requête. Si on a besoin d'attendre un résultat, au lie de placer une attente active qui va limiter la rapidité de traitement des autres informations, on va tout simplement affecter une callback à la requête, et cette callback sera exécutée lorsque le résultat sera arrivé. Au niveau système, il y a de grande chance que cette callback soient exécutée dans une autre thread dont la durée de vie sera très courte. Si l'OS choisi ne supporte pas les I/O asynchrones, c'est d'ailleurs comme ça qu'on procédera : au moment d'envoyer la requête, on crée une thread. C'est dans cette thread que la requête sera effectivement envoyée, une attente active sera effectuée, et la callback exécutée.

    Bon. On a résolu le cas de la base de donnée. Pour le log, c'est simple : ce n'est pas assez consommateur pour justifier sa séparation dans une thread. Résolu aussi.

    Reste les deux points abordés plus haut et sur lesquels on doit revenir :

    * envoi/reception de données
    * gestion du monde.

    La réception de donnée est un cas connu de goulot d'étranglement ; il faut pouvoir recevoir rapidement les données de plusieurs clients. Une thread suffira pour un petit nombre, mais dès lors que ce nombre grandit, il faut plus de thread. On affectera à cette tâche un pool de thread plutôt qu'une thread unique.

    Viens ensuite le traitement des données reçues. Le décodage peut totu à fait se faire dans la thread de réception, ainsi que les traitements courts à suivre. Par exemple, une requête "sélectionne telle arme" n'a pas besoin de faire des allers retour sur plusieurs thread. On reçoit la commande, on la traite, et on renvoie un acknowledge au client pour qu'il sache que la commande a été validée par le serveur. Mais si le traitement est plus long, il faut précéder autrement.

    On pourrait se dire : je vais faire comme pour les IO asynchrone, puisque conceptuellement, c'est ça. Sauf que le nombre de requêtes arrivant peut être important. C'est donc assez dangereux de procéder ainsi. Et puis ça rejoint la gestion du monde.

    Dans un monde, il n'y a pas que les personnages à gérer : il faut un moteur physique, ainsi que de nombreux autres systèmes qui peuvent être importants (gestion des combats, etc). Certains évènements particuliers provoquent l'envoi de messages à certains joueurs - cet envoi est effectué in situ si il n'y a pas trop de joueurs concernés, et déporté dans une thread à part dans le cas contraire.

    Prenons le cas suivant : un joueur frappe un mob, et celui-ci (en réponse) fait des dégâts en zone d'effet : tous les joueurs dans la zone autour du mob sont touchés. Au niveau des communications client/serveur, ça se passe comme ça :

    * client 1 : est-ce que je touche ma cible ?
    * serveur, thread de réception : décryption / analyse du message. Message complexe : on déporte le traitement.
    * serveur, thread de gestion de l'instance (la même thread peut gérer plusieurs instances) : vérification du coup porté ; renvoi de la réponse au joueur.
    * serveur, thread de gestion de l'instance : traitement supplémentaire : le mob inflige des dégâts de zone. Récupération de la liste des joueurs dans la zone déterminée. Si le nombre de joueur est faible, envoi de l'information "dégats reçu" à tous les joueurs. Sinon, on déporte le traitement.
    * serveur, thread de completion des envois lourd (il y a probablement plusieurs thread de ce type, afin de minimiser la latence au maximum) : envoi de l'information "dégâts reçus" à tous les joueurs concernés.

    Comme on le voit, la traitement d'un petit message peut soudain se transformer pour passer par différentes couches. Et je n'ai pas ajouté les gestion de la base de données dans le tas.

    Les threads à prévoir ne sont pas nécessairement dépendantes des différents modules implémentés dans le serveur : leur but est avant tout de réduire au maximum la latence (le temps entre la réception d'une commande et l'envoi de la réponse). Dans le même temps, ils contribuent à cette latence - pour le joueur effectuant l'action, le temps de réponse risque de s'alonger mais ça permet d'accepter les autres demandes plus rapidement. Au final, on y gagne quand même.

    L'analyse qu'il faut effectuer, c'est sur le flux des données - pas uniquement sur ce qu'elle subissent. Si beaucoup de données doivent être traitées pour une action donnée, alors cette action mérite peut-être sa propre thread, de manière à désengorger le traitement des autres actions. C'est de l'architecture système à ce niveau - comment faire pour que tout les processus qui collaborent sur différentes machines soient content ?

    Malheureusement, je t'aurais bien dit de ne pas prendre tout ça en compte au début de ton développement, mais le problème c'est que ce genre de chose ne peut pas s'implémenter une fois que tout est presque fini, sous peine de devoir tout recommencer.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Futur Membre du Club
    Inscrit en
    Décembre 2010
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    wouah ! Il est beau (et utile) ton roman

    Déjà, j'commence à y voir un peu plus clair, mais ce qui me rends fous, c'est de savoir combien peut coûter un serveur assez puissant pour faire cela sans ralentissement

    J'vais donc essayer quelque chose et j'reviens dans quelques jours avec ça, voir ce que vous en pensez

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Neo007 Voir le message
    wouah ! Il est beau (et utile) ton roman

    Déjà, j'commence à y voir un peu plus clair, mais ce qui me rends fous, c'est de savoir combien peut coûter un serveur assez puissant pour faire cela sans ralentissement

    J'vais donc essayer quelque chose et j'reviens dans quelques jours avec ça, voir ce que vous en pensez
    Le cout du serveur va dépendre du dimensionnement de ton MMO. En dessous de 100 joueurs, un PC récent simple (bonne nouvelle), avec une carte gigabit (ben oui, quand même), un disque dur rapide (si tu peux avoir la base de donnée sur du SSD, tu y gagneras bien) connecté à la fibre (ben oui, quand même aussi), ça suffira largement. Tu devrais pouvoir monter un peu en charge (il faudrait faire des benchs). Si tu commences à être limite, tu peux rajouter un PC en cluster, puis un autre, etc (ou concevoir ton programme de manière à distribuer la charge). Tant que tu ne vise pas la dizaine demilliers de joueurs, le coût matériel peut être relativement progressif.

    Au delà, je sais qu'IBM loue des serveurs Cell en baie (en fait, ils louent du temps processeur et de l'espace disque). Le coût n'est pas excessif, et ça peut permettre de passer le moment en creux où le nombre de joueur est trop important pour des petits serveur maison, mais trop peu pour une grosse infrastructure.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Futur Membre du Club
    Inscrit en
    Décembre 2010
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Bon, oui c'est sur que le matériel va progressivement augmenter de prix, mais en fait je parlais hébergement, parce que c'est sur que j'Vais aps héberger ça chez moi

    Petite question :

    Si on est 10 joueurs sur ma connexion internet, est-ce que c'est trop pour gérer les 10 clients sur ma bande d'upload ?

    test vidéotron :
    down : 513Ko/s
    up : 83 Ko/s

    Merci et bonne journée

  8. #8
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Neo007 Voir le message
    Bon, oui c'est sur que le matériel va progressivement augmenter de prix, mais en fait je parlais hébergement, parce que c'est sur que j'Vais aps héberger ça chez moi

    Petite question :

    Si on est 10 joueurs sur ma connexion internet, est-ce que c'est trop pour gérer les 10 clients sur ma bande d'upload ?

    test vidéotron :
    down : 513Ko/s
    up : 83 Ko/s

    Merci et bonne journée
    8ko par seconde par joueur, c'est beaucoup et c'est peu. C'est peu parce que ça risque d'être difficile à tenir (mais ce n'est pas impossible). Tu es limité à 800 octets par 100 ms, ce qui peut te permettre d'envoyer des messages courts et réguliers. Tu va devoir compenser par des systèmes type dead reckoning (c'est déjà nécessaire en temps normal, il va falloir que tu le fasse de manière vraiment intelligente).

    Et c'est beaucoup parce que si tu tiens ce débit, ça représente quand même 800 octet toutes les 100 ms. A de nombreux moments dans le jeu, tu n'auras pas besoin de ça.

    Je sais que ce que je vais proposer est à l'opposé de ce qui doit être fait pour un MMO, ou la centralisation des infos est importantes. Mais vu tes contraintes en bande passante, je me demande si tu ne devrais pas implémenter certaines choses en P2P plutôt que sur un serveur traditionnel.

    Ensuite, en termes d'hébergement de machines tout à fait correcte, je te propose de regarder ce que fait online.net avec ces dedibox. Ca coute une quarantaine d'euros par moi, et pour cette somme, tu loues un serveur (sur lequel tu installe ce que tu veux) qui est branché en direct sur le réseau free (et tu profites d'un débit assez important). C'est une solution possible si ta connexion est trop limite.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  9. #9
    Futur Membre du Club
    Inscrit en
    Décembre 2010
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    En fait, quand je parlais de ma connexion, ça sera uniquement pour faire des tests. Si jamais ça passe en version public, c'est que c'est un miracle je vais louer un serveur dédié

  10. #10
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 378
    Points
    20 378
    Par défaut
    Citation Envoyé par Neo007 Voir le message
    Déjà, j'commence à y voir un peu plus clair, mais ce qui me rends fous, c'est de savoir combien peut coûter un serveur assez puissant pour faire cela sans ralentissement
    minimum plus de 100euros par mois

  11. #11
    Membre régulier
    Homme Profil pro
    Architecte serveur
    Inscrit en
    Septembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte serveur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 64
    Points : 107
    Points
    107
    Par défaut
    J'arrive un peu tard, mais au pire, les connaissances consignées ici peuvent être utilisées bien après la 'mort' du thread.

    Je rejoins Emmanuel sur à peu prêt tout ce qu'il dit, je me permets de répondre après son message, créant quelques redondances, mais je pense qu'il vaut mieux qu'une information soit donnée deux fois quand elle est consensuelle.

    //Niveau facile (que je te conseille)

    Pour commencer, je serais direct, si tes connaissances en développement d'un serveur sont ce qu'elles semblent être (faibles), fais un serveur monothreadé.
    Sur des machines modernes, et si ton code est bien optimisé, tu peux aisément faire tourner quelques centaines de joueurs sur une pauvre machine, à fortiori un serveur (mes benchs sur un portable monocore (de 2005) indiquent qu'il peut tenir 1000 à 2000 requêtes/secondes, largement de quoi héberger quelques centaines de joueurs).
    Tu gagneras entre 200% et 400% de vitesse de coding (chiffre empirique et certainement un poil subjectif).

    Au niveau connexion, les échanges d'information s'ils sont bien gérés (messages de données binaires contenant exclusivement ce dont le client a besoin, sans envoyer de fichier) sont très faibles en taille. La moyenne de la taille d'une requête client->serveur est de l'ordre de 50-100 octets, la réponse du serveur est en gros deux fois plus grosse (là encore, je parle empiriquement). Donc la bande passante de la connexion me paraît secondaire.
    Le ping est plus important, en cela qu'il faut éviter d'atteindre les 250ms qui commencent à faire vraiment ressentir le lag.

    Un point important à prendre en compte si ton jeu est en temps réel, c'est la granularité des messages clients. Tu peux pas envoyer 100 fois par seconde la 'position' d'un joueur quand celui ci bouge, au risque de tuer ta connexion réseau et ton CPU serveur. Le choix de la granularité permet de fortement optimiser les échanges client/serveur. Sur Slage, ils utilisent une granularité de 300ms, et je pense que pour un jeu petit budget, tu peux approcher d'une granularité de 500ms/1s tant que ton gamedesign ne génère pas massivement des collisions entre les joueurs. Adapter la granularité au nombre de joueurs connectés à un instant donné te permettra d'avoir un jeu très agréable quand le serveur et vide, et toujours fonctionnel quand celui ci est plein.

    //Niveau moyen (évolution un peu plus performante du modèle précédent)

    Le master server. Utilisé essentiellement sur les jeux qui ne sont pas des MMOs (FPS, RTS), le master server permet d'augmenter les perfs de ton serveur conséquemment, tout en gardant l'illusion d'une architecture mono-threadé.
    Tout d'abord, découpe ton jeu en diverses parties distinctes sans relation entre elles (par exemple, des zones de jeu avec chargement entre elles). Héberge chacune de ces zones sur des serveurs séparés qui possèderont une architecture monothreadée comme celle décrite au dessus.
    Crée un master server, une sorte de proxy, qui suivant la position du joueur dans le monde, enverra ses informations sur le bon serveur. Le joueur pourra alors jouer sur ce serveur. Jusqu'à ce qu'il doive changer de serveur, moment ou le master server reprend la main en dirigeant la synchronisation entre le serveur de départ et le serveur d'arrivée.
    WoW utilise par exemple ce système avec ses instances qui sont toutes hébergées sur des serveurs différents du monde.
    /!\ Attention : Il faut faire en sorte d'exporter le maximum de traitements sur tes serveurs, et ne conserver que le minimum sur le master server. Sinon, c'est ton master server qui va 'mourir' avant tes serveurs dédiés. En général, on y garde uniquement la connexion et le chat (et encore, le chat est souvent géré par un autre serveur, spécialement dédié). Plus le master server aura de boulot et moins ton 'serveur' pourra héberger de joueurs.

    //Niveau difficile

    Le vrai serveur de MMO est tel qu'Emmanuel le décrit. Et là, honnêtement, le développement se compte en semestres. Le plus dur à gérer (d'expérience) est la synchronisation des données entre les divers threads de ton serveur. Si elle est trop importante, tu vas perdre trop en perf (voir finir avec du faux multi-thread à force de synchro), si elle est trop faible tu vas générer des incohérences, et risquer les fameuses collisions inter-threads (bug à occurence ultra rare et aléatoire sur lesquelles tu passeras des jours à temps complet).

    La connexion/authentification : Comme Emmanuel, une partie super importante, qui doit être multi-threadée ou exportée sur un autre serveur. Deux raisons à cela :
    - Si ton authentification est cryptée, elle va te coûter très cher en performances. Décrypter une chaîne en RSA prend 100 fois plus de temps que le traitement d'un message standard.
    - C'est la première à prendre dans la figure toutes les tentatives de hacking de style deny of service (comme dans cette partie je parle d'une vraie structure de MMO, je suis obligé de parler de hacking).

    La base de données : J'ai utilisé dans le domaine le MySQLConnector C++ et l'équivalent Java, toujours le même fonctionnement : Envoie de la requête à la bdd, wait, réception de la requête. Dans ce cas, obligation de multi-threader les appels bdd.
    Je ne connais pas les I/O asynchrones, mais ça à l'air bien. Par contre, quelles libs possèdent cette fonction, là, je ne sais.

    Au niveau de la description de la gestion du message, j'ai toujours utilisé (ou créé) des structures assez similaires à celle que décrit Emmanuel, mais avec moins de couches tout de même.
    En gros, le thread réseau récupère le message réseau, le désérialise et ensuite l'envoie vers le bon thread qui gère ce message. Le thread gère le message, puis renvoie vers le thread réseau ses réponses au(x) client(s).
    Tout le boulot a consisté à séparer les traitements entre un maximum de threads totalement indépendant (même concept que pour les serveur dédiés et le master server). Sur des archis de MMOs (j'ai bossé que sur des MMOs de combat tactique), je mets par exemple un(des) thread(s) de combat, un thread gérant le classement, un thread gérant la recherche de combat...

    //Les bugs que tu vas rencontrer (mieux vaut les connaître avant de devoir les corriger)

    Niveau facile : La gestion de la bdd. Elle va te faire rentrer de plein pied dans l'asynchronisme. Exemple typiques de bugs : le thread bdd (ou l'I/O asynchrone) renvoie le résultat d'une requête bdd alors que le joueur qui l'a demandé s'est déconnecté entre temps (oui oui, on peut se déconnecter en quelques millisecondes, et oui, ça te génèrera un bug impossible à reproduire).

    Niveau moyen : Les ghosts. Un ghost, c'est un joueur considéré comme connecté sur un thread/serveur dédié, alors qu'il est en fait déconnecté. Ca vient d'une mauvaise procédure de connexion/déconnexion (le bug bdd juste au dessus crée typiquement ce genre d'erreur quand la déco intervient pendant la procédure d'authentification). Le résultat est que ton personnage va apparaître dans le monde, car ton serveur dédié croira à son existence, alors que tu es déconnecté. Ca pose peu de problème... tant que tu ne te reconnectes pas.

    Niveau difficile : L'asynchronismedes données (valable dans mon modèle avec force séparation des tâches de chaque thread, moins valable dans le modèle d'Emmanuel qui fonctionne plus par couches). Tous tes threads auront des données différentes et asynchrones. L'exemple de bug le plus typique est la déconnexion pendant une synchronisation. Exemple, tu rentres en combat en pleine déconnexion. Le thread de combat peut recevoir ta déconnexion avant de recevoir le message de ton entrée en combat... et donc se mettre à manipuler un joueur déconnecté.
    C'est aussi la base de toutes les 'exploits'. Un thread possède une information, un autre en possède une autre, les deux informations habituellement incompatibles sont rendues compatibles par le fait que les threads ne sont pas au courant de ce qui se passe sur le thread voisin. Exemple : Je change (grâce à un bug client, ou un petit piratage de ma part) mon inventaire auprès du thread qui gère l'inventaire alors que je suis en train de perdre mon combat, résultat, à la fin du combat, c'est pas ma super arme de la mort qui sera cassée, mais l'arme toute pourrie que j'ai équipée entre temps.

    Dans tous les cas, je suis de l'avis que coder un MMO(RPG) est un très très gros défi pour un dév, à tous les niveaux (je connais mon domaine, mais je vois aussi le boulot des dévs client, et ils ne sont pas en reste en terme de difficulté).
    Mais même si l'entreprise me paraît folle, je te souhaite bonne chance (si tu es toujours dessus).

  12. #12
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    SuperBidi, ta réponse était vraiment très intéressante.

    Citation Envoyé par SuperBidi Voir le message
    La connexion/authentification : Comme Emmanuel, une partie super importante, qui doit être multi-threadée ou exportée sur un autre serveur. Deux raisons à cela :
    - Si ton authentification est cryptée, elle va te coûter très cher en performances. Décrypter une chaîne en RSA prend 100 fois plus de temps que le traitement d'un message standard.
    Je pense qu'il est possible d'éviter une telle encryption ; dans un premier temps, le client et le serveur dialoguent en utilisant RSA (ou un autre cryptogramme asymétrique), ce qui leur permet de se mettre d'accord sur une clef pour un algo symétrique - par exemple blowfish, relatvivement rapide comparé aux autres algorithmes disponibles, et bien moins utilisé qu'AES, ce qui rendra la tâche plus compliquée aux pirates (qui de toute façon, ne peuvent pas identifier l'algo utilisé en regardant les trames).

    Décoder du blowfish peut se faire relativement vite - et le code peut certainement être optimisé pour un langage particulier.

    Citation Envoyé par SuperBidi Voir le message
    - C'est la première à prendre dans la figure toutes les tentatives de hacking de style deny of service (comme dans cette partie je parle d'une vraie structure de MMO, je suis obligé de parler de hacking).
    Pour le coup, je croit que je laisserais faire le hardware : routeur, switch configurables, etc - bref, je mets des barrières matérielles là ou c'est possible pour capter la plupart des attaques. Certains projets de sécurité informatique peuvent être utilisés pour détecter au plus tôt les attaques de type DoS ou DDoS, ce qui donne la possibilité d'implémenter une contre mesure.

    Citation Envoyé par SuperBidi Voir le message
    La base de données : J'ai utilisé dans le domaine le MySQLConnector C++ et l'équivalent Java, toujours le même fonctionnement : Envoie de la requête à la bdd, wait, réception de la requête. Dans ce cas, obligation de multi-threader les appels bdd.
    Je ne connais pas les I/O asynchrones, mais ça à l'air bien. Par contre, quelles libs possèdent cette fonction, là, je ne sais.
    Le principe des IO asynchrone est intéressant, certes. D'expérience, c'est leur traitement qui peut devenir outrageusement complexe - avec cependant un gain énorme de temps à la clef. Sur une requête de BD, on lance la requête dans un thread, et c'est un autre thread qui reçoit le résultat. La thread émitrice peut donc continuer à travailler pendant le temps ou elle attends la réponse - mais à un moment, il faudra bien que ce résultat arrive. Le C++ nouvelle mouture a un concept de future et de promise : je te propose de regarder ces nouvelles fonctionnalités pour te faire une idée des possibilités. La lib asio propose les strand, un concept similaire (en fait, une thread d'attente a durée de vie courte qui exécute une callback une fois l'attente terminée).

    Le problème se dessine rapidement : le résultat arrive de manière asynchrone par rapport au traitement en cours.

    Deux solutions :

    1/ la thread émettrice effectue des opérations après l'émission de la requête, puis, une fois ces opérations terminées, attends le résultat de la requête.

    2/ la thread émettrice effectue quelques opérations après l'émission de la requête, et les traitement dépendant du résultat sont effectués dans le contexte de la callback exécutée à réception.

    Deux concepts différents, mais un résultat très similaire : à moins de trouver suffisamment de travail à faire dans la thread émettrice, elle devra attendre le résultat ou terminera son travail avant que le résultat ne soit reçu. Des cycles CPU seront donc gâchés.

    Tu vois tout de suite la difficulté à être dans le cas ou jamais on attendra qui que ce soit (à moins qu'on ait vraiment plus rien du tout à faire) sans pour autant être dans le cas ou les résultats sont traités longtemps après leur obtention (ce qui va ammener du lag dans le jeu).

    Intéressant donc, mais difficile à implémenter correctement dans la pratique.

    Citation Envoyé par SuperBidi Voir le message
    Au niveau de la description de la gestion du message, j'ai toujours utilisé (ou créé) des structures assez similaires à celle que décrit Emmanuel, mais avec moins de couches tout de même.
    En gros, le thread réseau récupère le message réseau, le désérialise et ensuite l'envoie vers le bon thread qui gère ce message. Le thread gère le message, puis renvoie vers le thread réseau ses réponses au(x) client(s).
    Tout le boulot a consisté à séparer les traitements entre un maximum de threads totalement indépendant (même concept que pour les serveur dédiés et le master server). Sur des archis de MMOs (j'ai bossé que sur des MMOs de combat tactique), je mets par exemple un(des) thread(s) de combat, un thread gérant le classement, un thread gérant la recherche de combat...
    Ca t'oblige pas à avoir plein de points de synchro ?

    Remarque, je n'ai pas vraiment d'architecture à proposer pour éviter ça,.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  13. #13
    Membre régulier
    Homme Profil pro
    Architecte serveur
    Inscrit en
    Septembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte serveur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 64
    Points : 107
    Points
    107
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Je pense qu'il est possible d'éviter une telle encryption
    En fait, je parlais exclusivement de la chaîne de connexion. Après coup, je n'utilise plus de cryptage, partant du principe que les données échangées en jeu ne sont pas importantes (contrairement aux identifiants de connexion). Alors que le coup en perf d'un cryptage permanent me paraît trop gros. Sur mon serveur je table sur - de 100 microsecondes par requêtes client. Alors, je connais pas blowfish, mais un cryptage de cette vitesse là qui peut pas être décrypté par force brute me paraît incroyable.

    Citation Envoyé par Emmanuel Deloget Voir le message
    Pour le coup, je croit que je laisserais faire le hardware : routeur, switch configurables, etc - bref, je mets des barrières matérielles là ou c'est possible pour capter la plupart des attaques. Certains projets de sécurité informatique peuvent être utilisés pour détecter au plus tôt les attaques de type DoS ou DDoS, ce qui donne la possibilité d'implémenter une contre mesure.
    Je suis pas du tout spécialiste hardware (et plutôt béotien en sécurité), mais tu connais du hard qui permette de se prémunir d'un DDoS sans bloquer complètement la connexion de nouveaux utilisateurs ?

    Citation Envoyé par Emmanuel Deloget Voir le message
    Ca t'oblige pas à avoir plein de points de synchro ?
    J'ai un seul mutex dans tout mon code (content ^^).
    Chaque thread est géré comme une entité indépendante, qui communique en utilisant des messages (basés sur la même interface que les messages client-serveur). En gros, chaque thread se balade avec une FIFO synchronisée de messages qu'il traite un à un, les autres threads se chargeant de la remplir.
    Ca permet de répondre aussi au problème de la bdd, vu que pendant que le thread bdd wait, les autres threads continuent leurs traitements peinards, et le résultat de la requête est un nouveau message envoyé au bon thread.

    D'ailleurs, en parlant de thread bdd, sur le serveur monothreadé, autant ne pas l'exporter sur un autre thread. Si la bdd est hébergée sur la même machine, le wait de l'appel bdd peut être très court. De plus, en général, on utilise des appels bdd à la connexion et déconnexion client et rarement le reste du temps, vu qu'on se base beaucoup plus sur les données en mémoire. Et comme le serveur est monothreadé, y a pas de perte de perf du au fonctionnement de la bdd, elle fonctionne pendant que le serveur wait.

  14. #14
    Membre régulier

    Profil pro
    Inscrit en
    Août 2006
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 60
    Points : 90
    Points
    90
    Par défaut
    Salut,
    je reviens juste sur la proposition d'Emmanuel Deloget sur la décentralisation du système ayant développé un solution similaire pour deux projets (un jeu de poker en ligne, et une ébauche de jeux de shoot) .

    En effet, cette solution est optimale pour certaines applications, mais comporte énormément de contraintes au moment de la programmation !
    Bien sur, tout n’est pas rose dans le monde merveilleux du décentralisé. La sécurité, l’intégrité des données et la validité des clients sont les principaux inconvénients/problèmes techniques que le système pose.

    Le jeu en ligne demande un TTL bas, un ping inférieur à 200 et une bande passante importante afin de ne pas retarder l'arrivée des paquets.
    Si une de ces conditions n'est pas respectée, l'expérience de jeu s'en trouvera extrêmement dégradée. C'est pourquoi les jeux vidéo en ligne continuent d'adopter une architecture client-serveur centralisée.

    Cependant, avec les débits et la latence toujours meilleure de nos lignes ADSL, l'hypothèse de faire un MMOx avec une architecture décentralisée devient de plus en plus réaliste et aujourd'hui, ce système est totalement réalisable.

    En effet, la serveur ne sera plus un point d'ancrage centrale pour toutes les communications (même si il reste un point d'ancrage central pour tout les clients.).

    Sachant que tous les paquets ne passent que par les clients, un client mal attentionné peut modifier les paquets à sa guise.
    De plus, les clients acceptants les paquets des autres clients, si un utilisateur décide de faire passer un code malicieux par le biais du logiciel, celui-ci se propagera rapidement au travers de toute la communauté.

    Première décision à prendre, y’aura-t-il un contrôleur maitre ?
    Le Contrôleur maitre est un serveur (ou client) vérifiant les opérations importantes. Dans la suite de l’article nous allons prendre la solution la plus simple pour la sécurité, une architecture avec la présence d’un contrôleur maitre. (si vous avez des questions sur la sécurité sans l’utilisation d’un contrôleur maitre posez moi les question en commentaire).
    Le contrôleur maitre vérifiera l’intégrité des paquets et tiendra à jour une liste des peers (clients) potentiellement dangereux et ceux de confiances. Quant un paquet arrivera d’un client et qu’un doute se pose sur l’intégrité de celui-ci (nous verrons le contrôle de l’intégrité dans un article prochain), il demandera simplement au contrôleur maitre de vérifier ce paquet. Ainsi, si le paquet est valide (si il respecte une architecture spéciale, que le hash est bon et que les informations correspondent aux regles du jeux il renverra un signal au client. Dans le cas contraire un message général sera envoyé à la totalité des peers mettant en garde contre ce client. Au bout du nième avertissement, ce client ne sera plus autorisé à émettre sur le réseau.

    Dans le cadre d’une application demandant un haut niveau de sécurité toutes les transactions importantes doivent être vérifiées par des contrôleurs maitres.

    Dans certains cas il est possible d’assigner certains utilisateurs comme contrôleurs maîtres (afin d'alléger le traitement du controleur maitre).

    Un controleur maitre peut par exemple (liste non-exhaustive) :
    - Controller aléatoirement des paquets en les demandant aléatoirement à des utilisateurs (afin de vérifier durant plusieurs secondes, que le comportement de ce jour ne soit pas anormal (déplacement, ....))
    - Réceptionner le hash d’un paquet afin de valider son intégrité au client demandeur
    - Tenir à jour une liste de client connecté/déconnecté
    - Empêcher des utilisateurs d’émettre.
    - Définir un client de confiance comme contrôleur maitre secondaire.

    Le controleur maitre ne sert vraiment qu'à maintenir une certaine intégrité sur le réseaux.

    Toutes les informations (déplacement, chat, ...) inhérentes au jeu sont toutes transmises d'un client a l'autre directement.

    Le principal problème dans un système décentralisé étant d'utiliser les ressources à dispositions. Certains peers ne vont disposer que de quelques Ko/s pour envoyer leurs informations aux autres peers tandis que d'autres vont disposer de plusieurs dizaines de Ko/s.

    Il faut ainsi choisir une architecture qui permette d’utiliser le maximum de chaque client. Pour cela, il faut créer une topologie dynamique (qui se met à jour en temps réel en fonction de l’environnement actuel et des clients connectés ainsi que leurs positions).

    Petit détail technique : les connexions entre les clients sont effectuées en UDP et non TCP.

    rien de bien compliqué, il suffit que le contrôleur maitre attribue à chaque client une liste de diffusion. Cependant, il faut tenir compte des contraintes techniques liées au MMOx, en l’occurrence garder un ping bas entre les joueurs. Pour cela il faut limiter le nombre de « saut »/ le nombre de clients qu’un paquet devra parcourir avant d’arriver à destination.


    Dans un MMOx, cette contrainte n’est importante que pour les joueurs proches (ceux qui peuvent nous voir) . Peu importe si la personne à l’autre bout de la map ne reçoit nos changements de position que 500ms après.
    Pour cela, il faut créer un algorithme capable de calculer la liste de diffusions pour chaque client, ainsi que sa liste de rediffusion c'est-à-dire la liste des clients auxquels ce client renverra les paquets qu’il recevra (en fonction de son origine).

    Enfin voila, grossièrement comment j'ai procédé. (bien sur tout est mieux ficelés mais j'avais la flemme d'écrire un roman )

  15. #15
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par SuperBidi Voir le message
    En fait, je parlais exclusivement de la chaîne de connexion. Après coup, je n'utilise plus de cryptage, partant du principe que les données échangées en jeu ne sont pas importantes (contrairement aux identifiants de connexion). Alors que le coup en perf d'un cryptage permanent me paraît trop gros. Sur mon serveur je table sur - de 100 microsecondes par requêtes client. Alors, je connais pas blowfish, mais un cryptage de cette vitesse là qui peut pas être décrypté par force brute me paraît incroyable.
    Sans encryption, tu as un risque de détournement/modification des données par un tiers (attaque du type man in the middle), qui peut dans les faits rançonner les utilisateurs pour qu'ils puissent continuer à jouer, voire les espionner pour en retirer un bénéfice quelconque. (par exemple connaître leurs position exacte, obtenir des infos sur leur équipement, détourner leur or, etc...).

    Citation Envoyé par SuperBidi Voir le message
    Je suis pas du tout spécialiste hardware (et plutôt béotien en sécurité), mais tu connais du hard qui permette de se prémunir d'un DDoS sans bloquer complètement la connexion de nouveaux utilisateurs ?
    Les attaques DDoS suivent très souvent des patterns (accès à une ressource particulière, ...). De plus, elles sont répétées en grand nombre à partir d'un nombre beaucoup moins important d'addresse. Après 3 tentatives de connexions dans un temps donné, on mets l'IP source dans un pack d'adresses suspectes. Si elle continue, on la route vers le Grand Vide (par exemple, on dit à un switch que cette adresse MAC n'est pas autorisée à accéder au réseau).

    Je te dis pas que c'est parfait comme protection, ni que c'est aisé à déterminer, mais c'est clairement faisable (c'est en partie comme ça que sont résolues les attaques DDoS sur les sites importants ; l'attaque prends fin une fois les contres-mesures mises en place, pas parce que les attaquants se sont dit "ok, là on a bien rigolé, on arrête").

    Citation Envoyé par SuperBidi Voir le message
    J'ai un seul mutex dans tout mon code (content ^^).
    Chaque thread est géré comme une entité indépendante, qui communique en utilisant des messages (basés sur la même interface que les messages client-serveur). En gros, chaque thread se balade avec une FIFO synchronisée de messages qu'il traite un à un, les autres threads se chargeant de la remplir.
    Ca permet de répondre aussi au problème de la bdd, vu que pendant que le thread bdd wait, les autres threads continuent leurs traitements peinards, et le résultat de la requête est un nouveau message envoyé au bon thread.
    Je serais curieux de savoir le temps que tu passes (en % du temps utilisé par le programme) dans ton mutex. Le ratio (temps non utile (=temps d'attente + temps dans la synchro) / temps total) serait aussi assez intéressant.

    Citation Envoyé par SuperBidi Voir le message
    D'ailleurs, en parlant de thread bdd, sur le serveur monothreadé, autant ne pas l'exporter sur un autre thread. Si la bdd est hébergée sur la même machine, le wait de l'appel bdd peut être très court. De plus, en général, on utilise des appels bdd à la connexion et déconnexion client et rarement le reste du temps, vu qu'on se base beaucoup plus sur les données en mémoire. Et comme le serveur est monothreadé, y a pas de perte de perf du au fonctionnement de la bdd, elle fonctionne pendant que le serveur wait.
    La DB sur la même machine, c'est un voeu pieu dès lors que ta DB contient les logs et les infos de plusieurs dizaine de milliers de joueurs. C'est vrai que dans un premier temps, tu peux toujours avoir une DB sur ta machine, quitte à la déporter ensuite lorsqu'elle devient trop importante. Dans les faits, ça veut dire que tu dois programmer le moteur en considérant que la DB est distante, et ce dès le début, sans quoi la migration risque de poser des problèmes graves.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  16. #16
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Maldus Voir le message
    Salut,
    Petit détail technique : les connexions entre les clients sont effectuées en UDP et non TCP.
    Je fais un petit apparté sur ce sujet spécifique.

    Contrairement à un shooter, les communications entre un client MMO et un serveur ont tout intérêt à ne PAS être perdues. De plus, la quantité de communication fait qu'il est préférable d'être en mode connecté (et donc laisser le HW gérer tout ce qui est attaché au protocole, y compris l'ordering des packets, le checksum, etc) sans quoi c'est au serveur de le faire. Un FPS peut se permettre de traiter les communications en mode datagramme (encore que), parce que le client passe sont temps à envoyer de nouvelles infos. Ce n'est pas nécessairement le cas dans un MMORPG, donc dans ce cas, TCP ne veut pas dire moins rapide que UDP - ça veut principalement dire plus sûr et que la plupart des traitements sont déportés sur une hardware spécialisé (principalement des switch et des routeurs).

    Du coup, on retrouve :

    * WoW en TCP
    * Lineage 2 en TCP
    * Guild Wars, si je me rappelle bien, en TCP.

    et tout une clique de jeux high profile qui utilisent TCP plutôt que UDP pour les communications.

    UDP pose aussi le problème du punch trough pour les configurations NAT (ce qui regroupe une grande majorité des configs ADSL actuelles). Le PT n'est pas toujours possibles, et le routeur pas forcément bien configuré, ce qui fait que le serveur ne peut pas envoyer de données au client si aucun échange n'a eu lieu "récemment" (la définition de "récemment" variant d'un routeur à l'autre). La aussi, on a un avantage au mode connecté.

    Je préconise TCP plutot que UDP dès que les quantités d'informations sont importantes et peu fréquentes (comme c'est généralement le cas pour un MMO).

    Pour un serveur de Poker, la problématique est légèrement différente : le serveur envoie très peu d'information à la fois (le client en envoie encore moins), mais le nombre de clients peut être très élevé. UDP est utilisé pour sauvegarder une partie de la bande passante. Si une erreur se produit et que le packet est discardé, il peut être réémis rapidement sur demande du client.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  17. #17
    Membre régulier
    Homme Profil pro
    Architecte serveur
    Inscrit en
    Septembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte serveur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 64
    Points : 107
    Points
    107
    Par défaut
    Edit : Je réponds à Maldus, les deux messages précédents sont arrivés pendant ma rédaction.

    Pour commencer, chapeau.
    J'ai déjà réfléchit à des systèmes décentralisés (car donnant plus de perfs) et j'ai vite abandonné l'idée.

    A cela, deux raisons :
    1. L'augmentation de la bande passante et des perfs serveur permettent de mettre de plus en plus de joueurs sur un seul serveur. Ce qui m'amène à la conclusion que plus le temps passe et moins il y a de justification à décentraliser.

    2. La sécurisation du système me paraît être un casse tête sans fin :

    Tu soulèves le problème de validation, qui peut devenir ultra problématique. Exemple, Bob est un joueur depuis très longtemps, Bob rentre donc dans la catégorie joueurs de confiance, voire contrôleur maître. Il peux donc, une fois, faire une action qui ne sera pas vérifiée. Si cette action met complètement en l'air le serveur (exemple : il annonce que le gobelin qu'il viens de tuer droppe excalibur), moi, j'aurais du mal à dormir.

    Deuxième point, tu donnes logiquement aux joueurs les adresses IP de leurs concurrents, ainsi qu'un process écoutant le port réseau du jeu (ton propre client). Autant je peux espérer protéger mon serveur contre toute forme de DOS et autre hack, autant je peux pas protéger facilement une machine client. Faire un DDOS sur tous tes adversaires te garantit une victoire facile. Et si en plus le client possède un bug, je donne la possibilité à un hacker de pénétrer sur des machines clientes. Qu'on pénètre sur mon serveur me ferait mal, mais qu'on fasse la même chose sur des machines clientes, et je suis bon pour pointer à l'ANPE.

    Après, il reste encore quelques points problématiques, comme la centralisation des données en bdd. Sur un MMO, elle est quand même assez conséquente, ce qui oblige dans tous les cas à avoir un serveur pour gérer les requêtes bdd (ça, tu en parles).
    Et aussi tous les problèmes de synchronisations. La synchro entre les clients est obligée de gérer le ping, résultat, je peux trafiquer les timestamp de mes requêtes pour donner l'impression que je vais plus 'vite' que les autres joueurs. Exemple (MMORPG) : je reçois l'info qu'un autre joueur me frappe, j'envoie un message antidaté au contrôleur maître indiquant que j'esquive son attaque, message qui arrive dans les délais grâce à mon super ping de la mort, est validé par le contrôleur maître et annule l'attaque que j'aurais du subir. Encore mieux, si je cumule avec l'exemple de Bob, je peux moi même être le contrôleur maître (en faisant une double connexion chez moi, une avec mon contrôleur maître, et une avec la machine avec laquelle je joue, et à ce moment là, je fais ce que je veux, vu que j'ai un ping de quelques millisecondes).

    Je ne sais comment tu as résolu toutes ces situations (mais suis intéressé si tu acceptes de donner tes petits trucs). Après, je suis peut-être trop attaché aux problèmes de sécurité.

  18. #18
    screetch
    Invité(e)
    Par défaut
    Il y a pas mal d'implémentations ou on gère des copies, et ou donc tout le monde peut modifier tout; ensuite on "merge" les données, quitte a rejeter un changement. On peut alors demander un recalcul par exemple; l'idée est qu'il est plus rapide de rejeter et refaire un calcul que de synchroniser tout le monde.

  19. #19
    Membre régulier
    Homme Profil pro
    Architecte serveur
    Inscrit en
    Septembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte serveur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 64
    Points : 107
    Points
    107
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Sans encryption, tu as un risque de détournement/modification des données par un tiers (attaque du type man in the middle), qui peut dans les faits rançonner les utilisateurs pour qu'ils puissent continuer à jouer, voire les espionner pour en retirer un bénéfice quelconque. (par exemple connaître leurs position exacte, obtenir des infos sur leur équipement, détourner leur or, etc...).
    Ca demande beaucoup de ressources : De 1, le gars doit pouvoir sniffer tous les paquets d'un client, de 2, il doit pouvoir les comprendre (donc avoir passé du temps en sniffing/décompilation). Le bénéfice est d'espionner les autres utilisateurs (ok, il sait où se trouve le joueur invisible) ou de trafiquer leurs paquets (là, c'est beaucoup plus génant). Après, j'ai réfléchi aux bénéfices qu'il pourrait en tirer, et pourrir un joueur quelconque dont il ne sait rien (sauf à ce qu'il soit en train de sniffer la connexion internet de sa propre maison) me paraît ne pas valoir le coût de faire une attaque de type man in the middle. Voler des identifiants de connexion le justifie beaucoup plus, d'où leur cryptage.
    Prendre des joueurs en otage me paraît super violent, en général, un craker préfèrera rester invisible.

    Citation Envoyé par Emmanuel Deloget Voir le message
    Les attaques DDoS suivent très souvent des patterns (accès à une ressource particulière, ...).
    Si je devais DDoS un serveur de MMO, j'utiliserai le pattern de la demande de connexion. Résultat, si mon attaque est vraiment distribuée, on ne peut la bloquer sans empêcher toute connexion au serveur.

    Citation Envoyé par Emmanuel Deloget Voir le message
    Je serais curieux de savoir le temps que tu passes (en % du temps utilisé par le programme) dans ton mutex. Le ratio (temps non utile (=temps d'attente + temps dans la synchro) / temps total) serait aussi assez intéressant.
    Alors, là, j'avouerai ne pas savoir comment mesurer cela.
    Ce que je sais :
    Je monte à plusieurs dizaines de threads (certains fonctionnent en parallèle, comme les threads d'écoute réseau et les threads bdd, donc je peux les multiplier à loisir). Donc quand un thread wait, un autre bosse.
    J'ai deux lignes de code à l'intérieur de mes deux synchronizes : Un "push();" d'un côté, et un "if (!isEmpty()) return pop();" de l'autre. J'aurais un doute que ce soit si long comme traitement.
    Mes threads communiquent tous entre eux, à l'exception des threads de même type lancés en parallèle. Donc si deux threads sont bloqués, le reste du serveur continue de fonctionner sans soucis. Il n'y a pas de 'centre' au réseau.

    Citation Envoyé par Emmanuel Deloget Voir le message
    La DB sur la même machine, c'est un voeu pieu dès lors que ta DB contient les logs et les infos de plusieurs dizaine de milliers de joueurs.
    Je parlais du cas du serveur monothreadé, l'exemple 'facile' que je présentais à Neo007. Bien évidemment, c'est pas valable sur un vrai serveur.

  20. #20
    Membre régulier

    Profil pro
    Inscrit en
    Août 2006
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 60
    Points : 90
    Points
    90
    Par défaut
    Salut à tous, alors voici comment j'ai procédé face aux différents problèmes. (Certe ce n'est peut être pas optimal, mais ca tient le choc jusqu'à maintenant !)

    Tu soulèves le problème de validation, qui peut devenir ultra problématique. Exemple, Bob est un joueur depuis très longtemps, Bob rentre donc dans la catégorie joueurs de confiance, voire contrôleur maître. Il peux donc, une fois, faire une action qui ne sera pas vérifiée. Si cette action met complètement en l'air le serveur (exemple : il annonce que le gobelin qu'il viens de tuer droppe excalibur), moi, j'aurais du mal à dormir.
    Au contraire, les actions des contrôleurs maîtres sont encore plus monitorée, car c'est en partie lui qui est un des relais de synchronisation du monde avec le server.
    Pour ce qui est de la modification de paquets, il faut de prime que la personne arrive à déchiffrer les paquets, ensuite, si la procédure d'émission de paquet n'est pas respectée, celui-ci ne sera pas valide. (Emission d'un hash au contrôleur maitre voisin, création des routes au timestamp t (une route non valide pour un timestamp t ne sera pas acceptée )).

    Donc en plus de déchiffrer les paquets, le client doit aussi mettre à nue le système de calcul de route ainsi que valider son paquet auprès du bon contrôleur.
    Pour le moment, personne ne s'est penché sur la question.

    Deuxième point, tu donnes logiquement aux joueurs les adresses IP de leurs concurrents, ainsi qu'un process écoutant le port réseau du jeu (ton propre client). Autant je peux espérer protéger mon serveur contre toute forme de DOS et autre hack, autant je peux pas protéger facilement une machine client. Faire un DDOS sur tous tes adversaires te garantit une victoire facile. Et si en plus le client possède un bug, je donne la possibilité à un hacker de pénétrer sur des machines clientes. Qu'on pénètre sur mon serveur me ferait mal, mais qu'on fasse la même chose sur des machines clientes, et je suis bon pour pointer à l'ANPE.
    Sur ce point, c'est effectivement très dangereux.
    Le jeu n'accepte qu'une certaine forme de paquet, validé par un contrôleur, .... (comme dit plus haut).
    De plus chaque joueur à une limite d'émission de paquet sur le réseau. Donc le réseau en lui-même ne peut pas être saturé.
    Cependant, il n'y a effectivement rien a faire contre un SYN-FLOOD direct de la ligne ADSL du client.
    C'est un des risques qu'il est impossible d'enlever.

    Après, il reste encore quelques points problématiques, comme la centralisation des données en bdd. Sur un MMO, elle est quand même assez conséquente, ce qui oblige dans tous les cas à avoir un serveur pour gérer les requêtes bdd (ça, tu en parles).
    Oui, sur ce point, chaque contrôleurs maitres communique avec le contrôleur principal afin de maintenir les informations de celui-ci "à jour".

    Et aussi tous les problèmes de synchronisations. La synchro entre les clients est obligée de gérer le ping, résultat, je peux trafiquer les timestamp de mes requêtes pour donner l'impression que je vais plus 'vite' que les autres joueurs. Exemple (MMORPG) : je reçois l'info qu'un autre joueur me frappe, j'envoie un message antidaté au contrôleur maître indiquant que j'esquive son attaque, message qui arrive dans les délais grâce à mon super ping de la mort, est validé par le contrôleur maître et annule l'attaque que j'aurais du subir. Encore mieux, si je cumule avec l'exemple de Bob, je peux moi même être le contrôleur maître (en faisant une double connexion chez moi, une avec mon contrôleur maître, et une avec la machine avec laquelle je joue, et à ce moment là, je fais ce que je veux, vu que j'ai un ping de quelques millisecondes).
    Justement, c'est la qu'intervient la validation des règles de jeux. Aléatoirement, les controleurs maitres peuvent demander aux clients une réexpedition de tout les paquets. Afin de controler que chacun est en accord avec les règles de jeux et qu'aucun abus n'est commis.

    Sur ce point, j'ai quelques doutes sur la fiabilité totale du système (je ne le cache pas), mais comme dit plus haut, il y a bien des choses a découvrir afin d'en arriver là.

Discussions similaires

  1. Recherche sur les différents moteurs rpg/mmorpg
    Par Phomos dans le forum Moteurs 3D
    Réponses: 5
    Dernier message: 08/10/2005, 16h57
  2. [C++] Creation d'un mmorpg
    Par washall dans le forum Projets
    Réponses: 22
    Dernier message: 16/08/2005, 18h16
  3. Réponses: 1
    Dernier message: 05/08/2005, 10h16
  4. Réponses: 1
    Dernier message: 05/07/2005, 18h07
  5. MMORPG quel language choisir ???
    Par Tomahna dans le forum Langages de programmation
    Réponses: 15
    Dernier message: 05/06/2005, 11h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo