Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [Résolu]Envoyer des packets séparés pour optimiser la bande passante..?  (Lu 2318 fois)

0 Membres et 1 Invité sur ce sujet

Slash94

  • Jr. Member
  • **
  • Messages: 89
    • Voir le profil
Salut à tous !

Alors voilà, je développe un petit jeu en ligne qui avance à vitesse grand V, néanmoins, pour les échanges réseaux, je procède de la sorte ( bon, je vulgarise ça un petit peu pour poster ma question ici ) :

sendPacket << username << x << y << state << mapzone << level;
 

Et bien entendu, de l'autre côté, on reçoit tout dans le même ordre, ça fonctionne parfaitement mais en fait, ça ne m'enchante pas de devoir tout renvoyer à chaque fois.. Ca bouffe de la bande passante et par conséquent, plus il y a de joueurs présents en ligne, plus ça lag..

Admettons que le personnage se déplace sur l'axe Y, j'aimerais que UNIQUEMENT la valeur de la variable Y soit envoyée et traitée de l'autre côté..
Comment donc pourrais-je m'y prendre pour que de l'autre côté, le serveur se dise " ÇA, c'est pour la variable Y ! "

J'ai tenté de faire un Packet différent pour chaque donnée envoyée et un packet de réception différent pour chaque réception mais ça arrive dans le désordre le plus total et puis ça me semble inutile, farfelu et complètement à côté de la plaque comme méthode..

Comment m'y prendre ?
Merci à tous, les amis :-]

PS : J'ai tenté de faire un petit code en guise de test avant de vouloir m'occuper de mon projet, mais c'est absolument pas fonctionnel du tout, lol.

Côté Serveur :
( J'ai crée un Packet pour recevoir les int X, Y et un autre Packet pour recevoir les strings mais cette méthode est complètement nulle et non fonctionnelle.. )

#include <iostream>
#include <vector>

#include <SFML/Network.hpp>

using namespace std;
using namespace sf;

int main()
{
    int port = 2000;
    bool done = false;

    TcpListener listener;
    SocketSelector selector;

    if (listener.listen(port) == Socket::Done)
        cout << "Serveur lance sur le port " << port << endl;
    else
        cout << "Impossible de lancer le serveur sur le port " << port << endl;

    listener.setBlocking(false);

    selector.add(listener);

    vector<TcpSocket*>clients;

    while (!done)
    {
        if (selector.wait())
        {
            if (selector.isReady(listener))
            {
                TcpSocket* socket = new TcpSocket;
                listener.accept(*socket);
                clients.push_back(socket);
                selector.add(*socket);

                Packet receivePacket;
                string pseudo;

                if (socket->receive(receivePacket) == Socket::Done)
                {
                    receivePacket >> pseudo;
                    cout << pseudo << " vient de se connecter." << endl;
                }

            } else {

                for (int i = 0 ; i < clients.size() ; i++)
                {
                    if (selector.isReady(*clients[i]))
                    {
                        Packet receivePacket, receivePacket2, sendPacket;
                        string str;

                        if (clients[i]->receive(receivePacket) == Socket::Done)
                        {
                            int x, y;
                            if (receivePacket >> x >> y)
                            {
                                cout << "recu de " << clients[i]->getRemoteAddress().getPublicAddress()
                                << " : x : " << x << " , y : " << y << endl;
                                sendPacket << x << y;
                            }

                            for (int j = 0 ; j < clients.size() ; j++)
                            {
                                if (i!=j)
                                    clients[j]->send(sendPacket);
                            }
                        }

                        if (clients[i]->receive(receivePacket2) == Socket::Done)
                        {
                            string str;
                            if (receivePacket2 >> str)
                            {
                                cout << "recu de " << clients[i]->getRemoteAddress().getPublicAddress()
                                << " : str = " << str << endl;
                                sendPacket << str;
                            }

                            for (int j = 0 ; j < clients.size() ; j++)
                            {
                                if (i!=j)
                                    clients[j]->send(sendPacket);
                            }
                        }
                    }
                }
            }
        }
    }
}
 

Mon Client de test :
(Quand on appui sur X ou Y ça incrémente les variables en question et quand on appuie sur S c'est censé envoyer la chaîne de caractère ).

#include <iostream>
#include <sstream>
#include <conio.h>

#include <SFML/Network.hpp>

using namespace std;
using namespace sf;

int main()
{
    bool done = false;
    string ip = "192.168.0.25";
    int port = 2000;

    TcpSocket socket;

    string pseudo;
    cout << "Votre pseudo : ";
    getline(cin,pseudo);

    if (socket.connect(ip, port) == Socket::Done)
    {
        cout << "connexion reussie ! " << endl;
        Packet sendPacket;
        socket.setBlocking(false);
        sendPacket << pseudo;
        socket.send(sendPacket);
    } else {
        cout << "echec de connexion... " << endl;
        exit(0);
    }

    int x = 0, y = 5;

    Clock clockSend;

    while (!done)
    {
        Packet sendPacket, sendPacket2;

        if (clockSend.getElapsedTime().asMilliseconds()>50)
        {
            if (_kbhit())
            {
                switch (_getch())
                {
                case 'x':
                    x++;
                    sendPacket << x << y;
                    socket.send(sendPacket);
                    break;
                case 'y':
                    y++;
                    sendPacket << x << y;
                    socket.send(sendPacket);
                    break;
                case 's':
                    sendPacket2 << "Lol!";
                    socket.send(sendPacket2);
                    break;
                }
            }
            clockSend.restart();
        }

        system("cls");
        cout << " x : " << x << " , y : " << y << endl;
    }
}
 
« Modifié: Avril 26, 2017, 09:41:33 pm par Slash94 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re: Envoyer des packets séparés pour optimiser la bande passante..?
« Réponse #1 le: Avril 23, 2017, 04:54:40 pm »
Citer
Comment donc pourrais-je m'y prendre pour que de l'autre côté, le serveur se dise " ÇA, c'est pour la variable Y ! "

enum CaCestQuoi : uint8_t
{
    CaCestLaVariableY,
    // ...
}

packet << CaCestLaVariableY << y;
 

if (socket.receive(packet) == sf::Socket::Done)
{
    uint8_t cestQuoi;
    packet >> cestQuoi;

    switch (cestQuoi)
    {
    case CaCestLaVariableY:
        packet >> y;
        break;

    // ...
    }
}
Laurent Gomila - SFML developer

Slash94

  • Jr. Member
  • **
  • Messages: 89
    • Voir le profil
Re: Envoyer des packets séparés pour optimiser la bande passante..?
« Réponse #2 le: Avril 24, 2017, 10:01:55 am »
Excellent Laurent !!!
Merci énormément, c'est une excellente technique et très simple qui plus est :-D

Slash94

  • Jr. Member
  • **
  • Messages: 89
    • Voir le profil
Re: Envoyer des packets séparés pour optimiser la bande passante..?
« Réponse #3 le: Avril 26, 2017, 09:10:41 pm »
Je reviens une dernière fois ici afin de vous informer que j'ai résolu le problème en surchargeant simplement les opérateurs << & >>, je n'utilise pas uint8_t mais directement l'envoi des valeurs énumérées et les réceptionne côté serveur, ça fonctionne du tonnerre !

Le lien que j'avais trouvé en pause à mon boulot sur mon téléphone qui m'a aidé à résoudre le problème :

https://en.sfml-dev.org/forums/index.php?topic=16295.0

Mes codes fonctionnels :

Côté Serveur

#include <iostream>
#include <vector>

#include <SFML/Network.hpp>

using namespace std;
using namespace sf;

enum DATA {Right, Up, Message};
Packet& operator>>(Packet& p, DATA& receiveData);

int main()
{
    int port = 2000;
    bool done = false;

    TcpListener listener;
    SocketSelector selector;

    if (listener.listen(port) == Socket::Done)
        cout << "Serveur lance sur le port " << port << endl;
    else
        cout << "Impossible de lancer le serveur sur le port " << port << endl;

    listener.setBlocking(false);

    selector.add(listener);

    vector<TcpSocket*>clients;

    while (!done)
    {
        if (selector.wait())
        {
            if (selector.isReady(listener))
            {
                TcpSocket* socket = new TcpSocket;
                listener.accept(*socket);
                clients.push_back(socket);
                selector.add(*socket);

                Packet receivePacket;
                string pseudo;

                if (socket->receive(receivePacket) == Socket::Done)
                {
                    receivePacket >> pseudo;
                    cout << pseudo << " vient de se connecter." << endl;
                }

            } else {

                for (int i = 0 ; i < clients.size() ; i++)
                {
                    if (selector.isReady(*clients[i]))
                    {
                        Packet receivePacket, sendPacket;

                        if (clients[i]->receive(receivePacket) == Socket::Done)
                        {
                            int checker;

                            receivePacket >> checker;

                            switch(checker)
                            {
                            case DATA::Right:
                                int x;
                                receivePacket >> x;
                                cout << "x : " << x << endl;
                                break;
                            case DATA::Up:
                                int y;
                                receivePacket >> y;
                                cout << "y : " << y << endl;
                                break;
                            case DATA::Message:
                                string str;
                                receivePacket >> str;
                                cout << "str : " << str << endl;
                                break;
                            }

                            for (int j = 0 ; j < clients.size() ; j++)
                            {
                                if (i!=j)
                                clients[j]->send(sendPacket);
                            }
                        }

                    }
                }
            }
        }
    }
}
 

Côté Client

#include <iostream>
#include <sstream>
#include <conio.h>

#include <SFML/Network.hpp>

using namespace std;
using namespace sf;

enum DATA {Right, Up, Message};

Packet& operator<<(Packet& packet, DATA& receiveData);

int main()
{
    bool done = false;
    string ip = "localhost";
    int port = 2000;

    TcpSocket socket;

    string pseudo;
    cout << "Votre pseudo : ";
    getline(cin,pseudo);

    if (socket.connect(ip, port) == Socket::Done)
    {
        cout << "connexion reussie ! " << endl;
        Packet sendPacket;
        socket.setBlocking(false);
        sendPacket << pseudo;
        socket.send(sendPacket);
    } else {
        cout << "echec de connexion... " << endl;
        exit(0);
    }

    int x = 0, y = 5;

    Clock clockSend;

    while (!done)
    {
            if (_kbhit())
            {
                Packet sendPacket;
                switch (_getch())
                {
                case 'x':
                    x++;
                    cout << " x : " << x << endl;
                    sendPacket << DATA::Right << x;
                    socket.send(sendPacket);
                break;
                case 'y':
                    y++;
                    cout << " y : " << y << endl;
                    sendPacket << DATA::Up << y;
                    socket.send(sendPacket);
                break;
                case 'm':
                    sendPacket << DATA::Message << "Lol.";
                    socket.send(sendPacket);
                    break;
                }
            }

    }
}
 

Merci une fois de plus à Laurent de m'avoir orienté vers cette superbe méthode d'optimisation !
Car sur mon jeu, à chaque nouvelle mise à jour ( admettons la position X de mon personnage ), je renvoyais TOUTES les informations ( pseudonyme, la map où il est, x, y, son level etc etccc ) ce qui était vraiment pourri de chez pourri comme méthode !

En espérant en avoir aidé à mon tour ! :-]
« Modifié: Avril 26, 2017, 09:22:41 pm par Slash94 »