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

Threads & Processus C++ Discussion :

Client Serveur multithread : problème


Sujet :

Threads & Processus C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 26
    Par défaut Client Serveur multithread : problème
    Bonjour,

    J'écris un petit jeu multijoueurs et j'ai un problème avec le serveur (ou le client je ne sais pas vraiment justement).
    Pour chaque joueur (chaque client) un nouveau thread est lancé, mais lorsque qu'un client envoi une donnée au serveur, tous les threads la recoivent :/
    Le but est d'envoyer au serveur chaque action (touche appuyée, touche relachée, ...), qui lui calcule les mouvements et renvoi les nouvelles coordonées.
    Si vous trouvez que cette architecture / méthode est mauvaise ou si vous avez des remarques quelconque n'hésitez pas!

    Comment ça marche, au niveau du serveur j'ai 2 classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Server {
        public:
            Server();
            ~Server();
            ...
        private:
            int nbrConnexions;
            int nbrPlayers;
            SOCKET serverSocket;
            SOCKADDR_IN serverSin;
     
            vector<Player*> players;
            ...
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Player {
        public:
            int numPlayer,x,y,state;
            SOCKET sock;
            SOCKADDR_IN sin;
     
            Player();
            ~Player();
            ...
            void start();
            DWORD WINAPI threadFunction();
            static DWORD WINAPI run(LPVOID lpParam);
            ...
     
        private:
            DWORD baseTickCount;
            DWORD threadId;
            HANDLE threadHandle;
            ...
     
    };
    Sur le serveur j'ouvre le socket pour se connecter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    WSADATA WSAData;
        WSAStartup(MAKEWORD(2,0), &WSAData);
     
        serverSocket = socket(AF_INET, SOCK_STREAM, 0);
        serverSin.sin_addr.s_addr			= INADDR_ANY;
        serverSin.sin_family				= AF_INET;
        serverSin.sin_port				= htons(PORT);
        bind(serverSocket, (SOCKADDR *)&serverSin, sizeof(serverSin));
     
        listen(serverSocket, 0);
    Puis j'attend les connections :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //preparation for an incoming player
        Player *p = new Player();
        p->numPlayer = nbrConnexions;
        players.push_back(p);
     
        int sinsize = sizeof(p->sin);
     
        while(1) {
            if( (p->sock = accept(serverSocket, (SOCKADDR *)&p->sin, &sinsize) ) != INVALID_SOCKET ) {
                cout << "New connexion : " << inet_ntoa( p->sin.sin_addr ) << ":" << ntohs( p->sin.sin_port ) << endl;
                p->start();
     
                nbrConnexions++;
                if (nbrConnexions == nbrPlayers) {
                    break;
                } else {
                    p = new Player();
                    p->numPlayer = nbrConnexions;
                    players.push_back(p);
                }
            }
        }
    p->start() lance le thread du joueur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    void Player::start() {
        threadHandle = CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)run, this, 0, &threadId);
    }
     
    DWORD WINAPI Player::run(LPVOID lpParam) {
        Player* p = (Player*)lpParam;
        return p->threadFunction();
    }
     
    DWORD WINAPI Player::threadFunction() {
     
        cout << "Thread created for player " << numPlayer << endl;
        ...
        while(1) {
            recv(sock, (char*)&gm, sizeof(GameMove), 0);
            ...
            cout << "received code " << gm.code << " at time " << getTime() << " from player " << numPlayer << endl;
        }
     
        terminate();
     
        return 0;
    }
    A chaque code envoyé par un client tous les threads affichent le message "received code XXX at time XXX from player X", où le numéro de joueur est correct (chaque thread recoit comme si "leur" client avait envoyé le code)

    Le client :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Client {
        public:
            Client();
            virtual ~Client();
            ...
            bool connexion(char* address);
            ...
        private:
            ...
            int x, y;
            int state, nbrPlayers, numPlayer;
            SOCKET sock;
            SOCKADDR_IN sin;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    bool Client::connexion(char* address) {
        ...
        cout << "Connexion...";
     
        WSADATA WSAData;
        WSAStartup(MAKEWORD(2,0), &WSAData);
     
        sin.sin_addr.s_addr	= inet_addr(address);
        sin.sin_family		= AF_INET;
        sin.sin_port		= htons(PORT);
        sock = socket(AF_INET,SOCK_STREAM,0);
        bind(sock, (SOCKADDR *)&sin, sizeof(sin));
     
        if (connect(sock, (SOCKADDR *)&sin, sizeof(sin)) == -1 ) {
            Console::pos(55, 11);
            cout << "Unable to connect";
            return false;
        }
     
        //lecture du numéro de joueur + version
        ...
        Console::pos(55, 11);
        cout << "Welcome player " << numPlayer;
     
        //attente des joueurs, dès que l'on reçoit les DataGame c'est bon
        ...
        return true;
    }
    Ensuite à chaque action sur le client j'execute ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void Client::keyboardEvent(int code) {
        GameMove gm;
        gm.code = code;
        ...
        //on envoi au serveur le mouvement
        send(sock, (char*)&gm, sizeof(GameMove), 0);
    }
    En fait c'est la 2ème version de cette appli que je fait, la première avait été mal conçue et les joueurs pouvaient avancer plus vite si ils avaient un meilleur ping lol. Je n'avais pas ce problème sur la v1 et le code des sockets a été quasiement copié collé.

    J'ai essayé plusieurs choses mais impossible de savoir d'où vient ce problème :/, si vous avez une idée ou si vous avez remarqué quelque chose qui ne va pas help merci

  2. #2
    Membre averti
    Inscrit en
    Juillet 2007
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 26
    Par défaut
    Edit :
    Le bug est résolu, en fait je me sers d'une boucle qui analyse l'état du clavier pour détecter avec précision l'appuie ou le relachement d'une touche. Je ne savais pas mais cette fonction fonctionne même si l'appli n'a pas le focus, vu que je fait tourner tous les clients sur la même machine, chaqu'un détectait la pression, et envoyait le code au serveur... il n'y avait donc aucun bug
    Si un modo passe par là il peut delete ce post

Discussions similaires

  1. application client-serveur multithread
    Par progcyb dans le forum Threads & Processus
    Réponses: 0
    Dernier message: 14/02/2015, 09h29
  2. Client / Serveur Multithread
    Par Dadar dans le forum Débuter avec Java
    Réponses: 10
    Dernier message: 20/06/2012, 11h07
  3. Déconnexion client/serveur multithread
    Par zpico dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 07/03/2012, 10h00
  4. Réponses: 2
    Dernier message: 28/04/2010, 03h15
  5. [client serveur multithread]Java
    Par Zay dans le forum Développement
    Réponses: 4
    Dernier message: 12/04/2007, 23h06

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