Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Algorithmique] Serveur UDP C++

Sujet résolu
    24 septembre 2015 à 20:40:17

    Bonjour,

    Voilà, alors actuellement je suis sur un projet qui requiert un serveur UDP (beaucoup d'échanges et doit être fait rapidement). Cependant, j'aurai deux questions.

    La première: comment les messages des échanges doivent être formatés ? Actuellement ce que je fais c'est que le client envoi un message du style "*CMD*PARAM1|PARAM2|PARAM3", et le serveur lira la nature de la commande (*CMD*) et s'occupera des paramètres de façon appropriée. Cela est-il la bonne manière de le faire ? Le message ne doit-il pas être compressé ?

    La Seconde: si par exemple sur le client j'ai dix objets, et les propriétés de cet objet doivent être mises à jours très rapidement, comment puis-je faire ? Actuellement, ce que je fais c'est que je créée des threads qui toutes le X millièmes de secondes demandent au serveur pour les différentes informations (qui sont des blocs contenant les infos pour les dix objets, donc un seul message pour tout avoir). Cela marche très bien, mais maintenant, j'ai 1200 objets, le serveur ne tient pas le truc, alors que je demande deux séries de 600 objets séparés par message contenants 200 objets, le problème c'est que le serveur lagg. A ce niveau là, je n'ai pas voulu faire un truc du style où le client demande individuellement pour chaque objet les infos quand il en a besoin car ça prendrait du temps pour la requête, mais aussi que les objets sont demandés par séries. Exemple, demande de 600 objets à la fois puis attente de 2 secondes. Comment puis-je faire pour résoudre ce problème ?

    Merci pour votre aide & bonne soirée :).

    -
    Edité par Ra'Jiska 24 septembre 2015 à 20:40:43

    • Partager sur Facebook
    • Partager sur Twitter
      25 septembre 2015 à 8:49:01

      Lu'!

      Première question : Ne passe que le strict minimum d'informations et sérialises les en binaires, pas en texte. Le plus simple étant encore d'utiliser à la fois une bibliothèque réseau adaptée et une bibliothèque de sérialisation adaptée. Boost fait les deux très bien (mieux que tu ne pourras l'écrire).

      Deuxième question : Créer des threads à tord et à travers c'est une très mauvaise idée, passer d'un thread à l'autre ça prend littéralement des plombes. Là tu as un gros défaut de conception. 600 objets à mettre à jour tous les quelques millisecondes depuis le réseau ? Elles consistent en quoi ces mises à jour ?

      • Partager sur Facebook
      • Partager sur Twitter

      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

        25 septembre 2015 à 14:34:08

        Bonjour,

        Merci pour ta réponse ! Pour la première question, quel est l'intérêt de sérialiser en binaire ? Cela ne fera pas des résultats plus longs au final ? Pour le réseau, j'utilise le header tout prêt winsock2.h pour Windows, cela ne convient-il pas ? Et ça roule pour boost, je crois que je vais l'utiliser car ça permet de faire plein de choses rapidement d'après ce que j'ai lu ailleurs.

        Pour la seconde question, du coup, je pense que je vais devoir rentrer un peu plus dans le détail sinon on ne va pas s'en sortir. Alors, actuellement je suis sur un projet avec un jeu contenant une map de campagne où il y a un joueur et les autres 'pions' IA (ça fonctionne avec un système où il y a un joueur qui host la partie et donc sa map qui est synchronisée avec les autres joueurs connectés). Il y a environ 600 pions IA et il faut les synchroniser (même ceux que le joueur ne voit pas encore). Pour cela, j'ai fais un objet par pion. Ces objets contiennent donc des méthodes pour définir la position de l'objet et des accesseurs pour récupérer ces positions (X, Y & Z). L'host de parties enverra les positions des pions toutes les X millisecondes au véritable serveur, et le serveur se chargera de renvoyer ces informations quand un client (n'étant pas host) en fait la demande (cette demande est actuellement faite avec les threads exécutés toutes les X millisecondes).

        Y aurait-il un moyen efficient pour résoudre ce problème ?

        Merci bien ^^.

        -
        Edité par Ra'Jiska 25 septembre 2015 à 14:36:09

        • Partager sur Facebook
        • Partager sur Twitter
          25 septembre 2015 à 16:10:15

          Ra'Jiska a écrit:

          (1) Pour la première question, quel est l'intérêt de sérialiser en binaire ? Cela ne fera pas des résultats plus longs au final ? (2) Pour le réseau, j'utilise le header tout prêt winsock2.h pour Windows, cela ne convient-il pas ? Et ça roule pour boost, je crois que je vais l'utiliser car ça permet de faire plein de choses rapidement d'après ce que j'ai lu ailleurs.

          (1) 255, ça rentre dans un octet, ça en demande 3 en texte. 65535, ça rentre dans 2 octets, ça en demande 5 en texte. Etc.

          (2) Hum ! Je sens d'ici le bon mélange de C et C++ qui sent la naphtaline et qui est tout plein de bugs en plus d'être chiant à écrire. Accessoirement, boost est portable. Pas winsock.

          Boost est une bibliothèque incontournable en C++.

          Ra'Jiska a écrit:

          Pour la seconde question, [...]. Alors, actuellement je suis sur un projet avec un jeu contenant une map de campagne où il y a un joueur et les autres 'pions' IA [...]. Il y a environ 600 pions IA et il faut les synchroniser [...]. Pour cela, j'ai fais un objet par pion. (1) Ces objets contiennent donc des méthodes pour définir la position de l'objet et des accesseurs pour récupérer ces positions (X, Y & Z). (2)  L'host de parties enverra les positions des pions toutes les X millisecondes au véritable serveur, et (3) le serveur se chargera de renvoyer ces informations quand un client (n'étant pas host) en fait la demande (cette demande est actuellement faite avec les threads exécutés toutes les X millisecondes).

          (1) Si c'est une classe avec juste des getters/setters, c'est pas objets, c'est juste de bête valeurs. Fais en des valeurs. Le but de l'encapsulation c'est protéger les invariants, s'il n'y en pas, n'encapsule pas.

          (2) Trop rapide, beaucoup trop rapide. De toute façon, le réseau ne suivra pas, des envois tous les demi-secondes, on serait déjà rapide.

          (3) On a 600 * 3 * 4 octets soit 7200 octets. C'est peanuts. A mon avis, le plus simple est simplement que la partie qui se charge de l'envoie aille checker rapidement tous les pions en packant ça dans un vector. Puis tu balances le contenu du vector et basta.

          • Partager sur Facebook
          • Partager sur Twitter

          Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

            25 septembre 2015 à 17:38:33

            Hmm, intéressant cette histoire de sérialisation. Et du coup, si on compresse le binaire avant de l'envoyer ce sera mieux ? Et ouep', il y a légèrement du C au niveau des actions réseau ^^. Du coup ça marche, je vais de ce pas voir ce que propose Boost et m'adapter !


            Après le truc c'est que les positions ce n'est qu'un début, je pense aller plus loin et par la suite avoir bien plus de choses bien que pour le moment ce ne soit effectivement que restreint aux setters/getters.

            Trop rapide ? Il doit pourtant y avoir un moyen. Par exemple pour les jeux contenants 200 à 500 joueurs, chaque joueur doit avoir la position du reste des clients, non ? Ou bien les jeux du style PlanetSide2, comment le transfert de milliers de joueurs se fait-il sur le client ?

            Concernant cette dernière partie, d'après ce que tu as dis, on devrait avoir 7200 octets par messages (avec la sérialisation), puis après, c'est effectivement ce que je fais, l'host de partie envoi la position de tous les pions au serveur puis chaque client ira faire une demande (actuellement avec un message du style '*CMD*') et le serveur renverra un message '*CMD*ID|X|Y|Z'.

            Merci :).

            • Partager sur Facebook
            • Partager sur Twitter
              25 septembre 2015 à 17:46:20

              Ra'Jiska a écrit:

              Et du coup, si on compresse le binaire avant de l'envoyer ce sera mieux ?

              Non. L'entropie sera trop grande et tu perdras ton temps à compresser/décompresser.

              Ra'Jiska a écrit:

              Après le truc c'est que les positions ce n'est qu'un début, je pense aller plus loin et par la suite avoir bien plus de choses bien que pour le moment ce ne soit effectivement que restreint aux setters/getters.

              Les setters c'est mal. C'est du viol sauvage de l'objet. Quant à avoir plus de choses : une classe = une responsabilité.

              Ra'Jiska a écrit:

              Trop rapide ? Il doit pourtant y avoir un moyen. Par exemple pour les jeux contenants 200 à 500 joueurs, chaque joueur doit avoir la position du reste des clients, non ? Ou bien les jeux du style PlanetSide2, comment le transfert de milliers de joueurs se fait-il sur le client ?

              Sur les MMO la position des joueurs, c'est mis à jour toutes les secondes environ pour les éléments qui ont une possibilité d'interaction directe. Pour les autres, ça peut être "beaucoup" plus long.

              Ra'Jiska a écrit:

              Concernant cette dernière partie, d'après ce que tu as dis, on devrait avoir 7200 octets par messages (avec la sérialisation), puis après, c'est effectivement ce que je fais, l'host de partie envoi la position de tous les pions au serveur puis chaque client ira faire une demande (actuellement avec un message du style '*CMD*') et le serveur renverra un message '*CMD*ID|X|Y|Z'.

              Pas la peine de restreindre vraiment la quantité de données. Il faut surtout restreindre la quantité de requête. Traverser la couche réseau, ça prends toujours un peu de temps et si le traitement de tes données est plus rapide que ce temps, alors ça ne vaut vraiment pas le coup de faire un message par pion.

              • Partager sur Facebook
              • Partager sur Twitter

              Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                26 septembre 2015 à 9:14:43

                Ok, ça marche, c'est tout ce dont j'avais besoin de savoir.

                Merci beaucoup pour ton aide Ksass ! :honte:

                • Partager sur Facebook
                • Partager sur Twitter

                [Algorithmique] Serveur UDP C++

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown