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; ... };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
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; ... };
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 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);
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 //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); } } }
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)
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; }
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; };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
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; }
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é.
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); }
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![]()
Partager