Jeu en reseau, probleme de lag!

Jeu en reseau, probleme de lag! - Java - Programmation

Marsh Posté le 23-06-2006 à 15:29:02    

Bonjour !
 
Je programme en ce moment un petit jeu 2D tout simple ou des personnages se baladent sur une carte.
 
Il y a un programme client, et un programme server. (en passant merci a ceux qui m'ont aidé a regler mes problemes de serialisation!!).
 
Ca marche comme ceci : le serveur ecoute ce qui arrive sur le port 4000, j'ai crée des threads pour gerer plusieurs connexions a la fois.
 
Le client envoie au serveur, toutes les 20 ms (c'est peut etre trop rapide?), un objet contenant l'id du joueur, et 4 booleans indiquant les touches sur lesquelles appuie le joueur, pour gerer le deplacement.
 
Le serveur recoit l'objet, traite l'information, met a jour la position du joueur, et renvoie une liste contenant les positions de tous les joueurs present sur le serveur.
 
Le client recoit cette liste, et affiche les joueurs. Comme je l'ai dis, le rendu se fait toutes les 20 ms, ainsi que l'envoie de l'objet.
 
Tout marche bien en local, mais quand je demande a quelqu'un de tester le jeu par internet, en rentrant son adresse IP, et que je me connecte au serveur qu'il a lancé, ca lag comme pas possible chez moi!
 
Par contre chez lui ca tourne bien puisque c'est en local!
 
D'ou mon interrogation : a piori les objets que se communiquent serveur et client ne sont pas de taille surdimensionné, y'a t'il un autre probleme quelque part? Peut etre je m'y suis mal pris? (c'est la premiere fois que je code un programme utilisant le reseau..) , je pense aux jeux en reseau moderne qui doivent s'envoyer pas mal d'information , et tout ca se fait de maniere fluide, tandis que moi, je n'envoie que de simples coordonées, et ca lag ..
Comment faire pour que ceux qui jouent en local et ceux qui joue a distance se deplacent a la meme vitesse?
 
Merci !

Reply

Marsh Posté le 23-06-2006 à 15:29:02   

Reply

Marsh Posté le 23-06-2006 à 15:32:57    

Y'a pas un truc de tcp ou udp pour augmenter la vitesse de com au détriment de la qualité de reception ? Je crois que quake utilise udp pour avoir de bonnes perfs.

Reply

Marsh Posté le 23-06-2006 à 15:33:58    

mon programme utilise du TCP pour communiquer, ca viendrait de la?

Reply

Marsh Posté le 23-06-2006 à 15:39:49    

non. rien à voir. Déjà cet intervalle arbitraire de 20ms est stupide. Tout le monde doit envoyer ses données des qu'il le peut.

Reply

Marsh Posté le 23-06-2006 à 15:42:14    

en fait les 20 ms viennent de l'affichage, et j'ai mis les echanges dans le meme thread, il faudrait donc que je separe affichage et communication ?

Reply

Marsh Posté le 23-06-2006 à 15:44:57    

ben pourquoi affichage et communication seraient liés ?

Reply

Marsh Posté le 23-06-2006 à 15:48:26    

c'est vrai c'est stupide ^^
 
j'essai ca et je vous tiens au courant du resultat  :)  
merci!

Reply

Marsh Posté le 23-06-2006 à 16:14:18    

Voila donc j'ai separé affichage et communication, j'ai crée 1 thread pour chaque !
 
Mais le probleme de lag persiste toujours ! sur un serveur distant je recois environ 2 objets par seconde, alors que pour que ce soit fluide, je suis censé en recevoir une cinquentaine.
 
De plus le joueur en local lui va vite, contrairement a moi qui bouge super lentement ..
 
Quelqu'un aurai tune solution? :(

Reply

Marsh Posté le 23-06-2006 à 16:18:56    

Quel est ton protocol ?

Reply

Marsh Posté le 23-06-2006 à 16:28:02    

j'utilise TCP

Reply

Marsh Posté le 23-06-2006 à 16:28:02   

Reply

Marsh Posté le 23-06-2006 à 16:28:24    

le protocole de ton jeu :o

Reply

Marsh Posté le 23-06-2006 à 16:37:35    

heu tu pourrais preciser je comprend pas de quoi tu veux parler? ^^

Reply

Marsh Posté le 23-06-2006 à 16:39:04    

Comment sont formée les informations que tu envoies à ton serveur ?
 
Sont-elles bufferisées ? Concaténées ? Distinguées ?

Reply

Marsh Posté le 23-06-2006 à 16:45:22    

Ce sont des objets serialisables j'utilise des instructions de ce type :
 
D'abord j'ouvre les flux :

Code :
  1. /**Flux d'entrée et de sortie*/
  2. ObjectOutputStream oos = new ObjectOutputStream(serveur.getOutputStream());
  3. ObjectInputStream ois = new ObjectInputStream(serveur.getInputStream());


 
Puis j'envoie les objets et j'en recupere d'autres :
 

Code :
  1. /*Envoie au serveur*/
  2. oos.writeObject(action);
  3. /**Recuperation du boolean qui indique si la partie est finie ou non*/
  4. int fini = (int)(ois.readInt());
  5.                  
  6. /**On recupere la liste et on met a jour*/
  7. ListEntite listeInc;
  8. listeInc = (ListEntite)(ois.readObject());
  9. changelist(listeInc);


 
Les objets action sont formée d'un int et de 4 booleans, les objets ListEntite sont une arraylist d'entité, qui elles sont formée de 3 int et de 2 booleans.
 
je ne sais pas si je repond a ta question  :??:

Reply

Marsh Posté le 23-06-2006 à 16:49:02    

essaye 15 ms

Reply

Marsh Posté le 23-06-2006 à 16:50:57    

j'ai enlevé cette limite en temps pour le thread concernant la communication, elle reste juste pour l'affichage!
 
edit : je vais changer la structure pour faire en sorte que le serveur envoie des infos uniquement quand il y a eu une modification d'un des joueurs .. si il ne se passe rien, le serveur n'envoie rien !
je vais peute tre gagner de la bande passante avec ca!


Message édité par Phraides le 23-06-2006 à 17:05:15
Reply

Marsh Posté le 23-06-2006 à 17:04:48    

Phraides a écrit :

Ce sont des objets serialisables j'utilise des instructions de ce type :
 
D'abord j'ouvre les flux :

Code :
  1. /**Flux d'entrée et de sortie*/
  2. ObjectOutputStream oos = new ObjectOutputStream(serveur.getOutputStream());
  3. ObjectInputStream ois = new ObjectInputStream(serveur.getInputStream());


 
Puis j'envoie les objets et j'en recupere d'autres :
 

Code :
  1. /*Envoie au serveur*/
  2. oos.writeObject(action);
  3. /**Recuperation du boolean qui indique si la partie est finie ou non*/
  4. int fini = (int)(ois.readInt());
  5.                  
  6. /**On recupere la liste et on met a jour*/
  7. ListEntite listeInc;
  8. listeInc = (ListEntite)(ois.readObject());
  9. changelist(listeInc);


 
Les objets action sont formée d'un int et de 4 booleans, les objets ListEntite sont une arraylist d'entité, qui elles sont formée de 3 int et de 2 booleans.
 
je ne sais pas si je repond a ta question  :??:


 
 
Y'aurais pas une options sur tes sockets qui fait que le buffer d'envoi sur socket attend d'etre plein pour être envoyé ? Si c'est ça, il se peut que, pour une trame reçue, tu aies en fait beaucoup plus qu'une trame, les serialisations de tes objets étant concaténées les unes aux autres.


Message édité par _darkalt3_ le 23-06-2006 à 17:05:22
Reply

Marsh Posté le 23-06-2006 à 17:09:49    

Bonjour, je me suis inscrit expres pour te répondre :)
J'ai réalisé pas mal de petits jeux en réseaux et au début j'avais exactement le même problème que toi.
Bon j'essaierai de ne pas trop troller sur le fait que tu fasses ça en java mais c'est vrai que ca ne doit pas aider au probleme :)
 
Alors tout d'abord si il s'agit d'informations que tu envoies en continue et qui ne sont pas obligatoire ( une position par exemple ) il vaut mieux les envoyer en udp : en effet la transmission sera beaucoup plus rapide.
Par contre si il s'agit d'une information capitale ( qui doit absolument arriver a destination : un tir ou un pseudo par exemple ) il vaut mieux l'envoyer en TCP ou alors te faire ton propre algo d'accusé re deception en UDP.
 
Pour ce qui est de la fréquence de transmission l'envoyer toutes les 20ms n'a rien d'idiot et c'est bien ainsi qu'il faut procéder pour envoyer les données continues ( positions et etat des touches).
 
Ensuite comme ton client va recevoir la position toutes les 20ms il va bien falloir afficher quelque chose si un un packet met trop de temps a arriver : ton client doit donc prevoir ce qui arrive au joueur : tu as la position + l'état du clavier : a toi de déplacer le joueur pendant qu'aucun packet n'est recu puis de corriger ensuite lors de la reception du packet...
 
Enfin je crois que la sérialisation n'est vraiment pas la meilleur solution puisque cela ajoute un en-tête pour le moins encombrant !
 
Voilà j'espere avoir fait le tour si tu as des questions n'hésites pas !


Message édité par MoDDiB le 23-06-2006 à 17:12:28
Reply

Marsh Posté le 23-06-2006 à 17:12:00    

Merci beaucoup pour ces precision  :)  :)  
 
je vais essayer ca et je vous tiens au courant sur ce post !
 
PS: tu me conseillerai quel langage pour ce type d'application?

Message cité 2 fois
Message édité par Phraides le 23-06-2006 à 17:15:07
Reply

Marsh Posté le 23-06-2006 à 17:15:58    

Phraides a écrit :

Merci beaucoup pour ces precision  :)  :)  
 
je vais essayer ca et je vous tiens au courant sur ce topic !
 
PS: tu me conseillerai quel langage pour ce type d'application?


 [:aloy]  
 
c++

Reply

Marsh Posté le 23-06-2006 à 17:29:28    

fais des flush apres tes écritures, pour forcer l'envoi de ton message.

Reply

Marsh Posté le 23-06-2006 à 18:16:23    

Evidemment je conseille le C++ mais normalement pour le jeu que tu développes le JAVA est plus que suffisant ca ne devrait pas du tout poser de problèmes je trollais juste un peu pour la route :)
 
Sinon voici 2 articles qui m'ont bien aidé :
http://www.gamedev.net/reference/a [...] cle914.asp
http://www.gamasutra.com/features/ [...] son_01.htm
 
Amuses toi bien :)

Reply

Marsh Posté le 23-06-2006 à 21:46:29    

j'ai joué un peu pour voir et je pense que si tu vois du 'lag' c'est parce que  :
- soit tu fais des Thread.sleep avant tes read. Profite du fait que read est bloquant.
- tu a rajouté une couche de buffered, là il faut que tu flush après un write, pour forcer l'envoi. ça vaut parce que dans ton cas, il s'agit d'un dialogue, on parle chacun son tour si je comprends bien.

Reply

Marsh Posté le 23-06-2006 à 23:17:25    

Phraides a écrit :

Merci beaucoup pour ces precision  :)  :)  
 
je vais essayer ca et je vous tiens au courant sur ce post !
 
PS: tu me conseillerai quel langage pour ce type d'application?


 
C# bien evidemment


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 24-06-2006 à 00:24:25    

... je vois pas le rapport avec le langage de programmation. dès que le langage est décent et propose une bibliothèque fournit, ça ne pose aucun problème.

Reply

Marsh Posté le 26-06-2006 à 11:43:41    

tu sous entends que Java n'est pas un langage décent ?


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 26-06-2006 à 12:04:45    

Tamahome a écrit :

tu sous entends que Java n'est pas un langage décent ?


 
on est pas vendredi :o


Message édité par _darkalt3_ le 26-06-2006 à 12:05:08
Reply

Marsh Posté le 28-06-2006 à 22:57:40    

Hop je remonte mon post pour vous demander quelques precisions !
 
 
J'ai programmé ce petit jeu avec une structure client server en java, et aussi en C++ pour voir si ca allais mieux marcher.
 
Je me suis rendu compte qu'outre le probleme du lag qui peut etre resolu avec ce que vous m'avez conseillé, j'ai un enorme probleme d'utilisation du processeur :
 
que ce soit en java ou en c++, mon serveur qui utilise une methode tcp bloquante d'ecoute pour enregistrer ce qui arrive, utilise de 50 a 100% de mon processeur!
 
le programme a une structure comme ceci :
 

Code :
  1. initialisation
  2. while(!condition arret)
  3. {
  4. ecoute de ce qui arrive sur le port [methode bloquante!]
  5. traitement
  6. }
  7. fin


 
A priori quand le server est en ecoute vu que la methode est bloquant je ne vois pas pourquoi il utilise tout mon processeur !?
Que ce soit avec ou sans thread j'ai le meme probleme !
 
Si quelqu'un a une idée!
 
Merci!!

Reply

Marsh Posté le 28-06-2006 à 23:08:09    

tu bufferises ? sinon il se peut que ton read, bien que bloquant, lise octet par octet et déclenche des tas d'itérations. Est-ce que tu as ce taux élevé de CPU même au démarrage alors qu'aucun client ne s'est connecté ?

Reply

Marsh Posté le 28-06-2006 à 23:16:59    

en fait oui j'ai le meme taux d'utilisation quand personne n'est connecté, quand le serveur est en mode "accept", en attente d'une connexion ...
 
et qu'entend tu par bufferiser? je transfert les données objets par objets, avec serialisation en java, et juste avec un cast en c++ (j'utilise la librairie SDL)


Message édité par Phraides le 28-06-2006 à 23:18:46
Reply

Marsh Posté le 28-06-2006 à 23:22:58    

mets un print dans ta boucle voir si elle tourne ...
 
normalement accept() bloque, tu es sur de ne pas avoir rater une étape ?

Reply

Marsh Posté le 28-06-2006 à 23:30:02    

ah oui alors en fait avec la librairie SDLNet on dirait que accept() c'est pas bloquante  :heink: ! ca m'etonne !
 
du coup si je met pas mon   client=SDLNet_TCP_Accept(server);    
dans une boucle infinie, le programme se lance et s'eteint directement ...
 
 
y'a pas un moyen pour la "rendre" bloquante,? Peut etre que je devrais pas utiliser SDL pour le coté reseau?


Message édité par Phraides le 28-06-2006 à 23:33:51
Reply

Marsh Posté le 28-06-2006 à 23:43:11    

pourquoi tu ne fais plus de java ?

Reply

Marsh Posté le 28-06-2006 à 23:51:39    

mon jeu lagguait beaucoup trop j'avais fais un "moteur" 2D a la main je me suis dis je vais utiliser SDL et pourquoi pas changer de langage aussi pour voir si ca allais refaire les memes problemes ..
 
J'ai refais des tests :
 
avant que je ne me connecte y'a une boucle avec le accept() , et ca rame a fond
 
mais quand je me connecte, avec la methode Recv() qui elle est bloquante, ca n'utilise plus du tout du processeur ... donc en fait si le accept() etait bloquant j'aurais résolu mon probleme ^^

Reply

Marsh Posté le 28-06-2006 à 23:59:24    

fait un select/poll/epoll

Reply

Marsh Posté le 29-06-2006 à 00:13:15    

heuu tu pourrais preciser le fond de ta pensée?
 
 :D

Reply

Marsh Posté le 29-06-2006 à 10:21:37    

ben tu ne fais plus d'attente active sur ton socket, tu boucles avec un select/poll/epoll dessus (man poll) qui vont te permettre de rajouter une temporisation pour ne pas manger tout ton CPU. temporisation infinie si tu le veux d'ailleurs (rendre bloquant)

Reply

Marsh Posté le 29-06-2006 à 13:49:22    

mets des points d'arret et regarde ce qui se passe


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 29-06-2006 à 13:49:51    

"man poll" c'est super s'il est sous windows...


---------------
Hobby eien /人◕ ‿‿ ◕人\
Reply

Marsh Posté le 29-06-2006 à 13:54:31    

supposons qu'il aura traduit de lui même :o

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed