Serveur ; pertes de données

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
stombretrooper
Messages : 117
Inscription : dim. 21/déc./2008 18:39

Serveur ; pertes de données

Message par stombretrooper »

Je codes toujours mon serveur j'ai un problème qui peut parraitre idiot ; J'envoie plusieurs messages en même temps le problème c'est que le serveur récupères des données mais pas toute, certaine sont perdus car le serveur n'a pas le temps de les traiter :? comment pourrais-je faire pour éviter de perdre des messages ? :wink:
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

As - tu un bout de code ?

Ça vient certainement du fait que tu ne traites pas toutes tes données dans ton buffer de réception. Si tu lis 500 octets mais que tu en reçois 600, il y a 100 octets qui passent à la trappe :/

Le second souci qui peut expliquer cela, c'est si tu utilises le protocole UDP. En UDP la connexion n'est pas explicite, en gros ton paquet de données part mais l'envoyeur ne sait jamais s'il le destinataire l'a reçu. A l'inverse grâce à TCP, le protocole te garantit que tes données sont reçus (sachant que les données peuvent être reçues sans être correctement traitées !).
stombretrooper
Messages : 117
Inscription : dim. 21/déc./2008 18:39

Message par stombretrooper »

Sa n'a rien à voir je m'explique ; je code un MMO RPG il existe plusieurs types de message reconnus par des identifiant (ses identifiant son le premier byte du message) quand je me déplaces j'envoie le message 4 avec mes positions x et y, quand j'envoie le message 5 il contient aussi un message qui sera afficher dans le chat maintenant quand je me déplaces et que j'envoie un message dans le chat un des deux messages n'est pas reçu sur le serveur je penses que c'est parce que pendant que le serveur traite un message il 'oublie' de traiter l'autre :?

J'utilise le protocole tcp et j'ai quand j'envoie les messages séparément je les traites sans problème
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Le serveur ne peut pas oublier de traiter un message. Il le met en file d'attente pour le traiter après.

Un peu de code (même peu) permettrait d'y voir un peu plus clair.

1 chose néanmoins : es - tu sûr que les 2 messages partent bien ?

(désolé c'est basique mais faut toujours commencer par tester les problèmes potentiels les plus simples, surtout quand on fait du réseau :))
stombretrooper
Messages : 117
Inscription : dim. 21/déc./2008 18:39

Message par stombretrooper »

Bien sur :)

Donc ce code créer un thread par donné à traiter ;

Code : Tout sélectionner

Procedure acceuil_client(lecture)
If CreateNetworkServer(0,14804,#PB_Network_TCP)

Repeat
  eve=NetworkServerEvent()
  While eve=0
  Delay(1)
  eve=NetworkServerEvent()
  Wend
  Select eve
    Case 1;nouveau client connecté
    joueur_nombre=joueur_nombre+1
    value=cherche_sock(0)
    Joueur(value)\compte_sock=EventClient()
    GetHttp("http://kraessor.free.fr/GAME/gestion_connecte.php?operation=true");ajoute un connecté sur le site web
    
    Case 2;nouvelle envoie de données
    LockMutex(traite)
    *s=AllocateMemory(1000)
    ReceiveNetworkData(EventClient(),*s+4,1000)
    Delay(10)
    joueuralpha=EventClient()
    CreateThread(@traitement(), *s)
    
    Case 3;nouvelle envoie de fichier sa peut servir pour la suite ^^
    
    Case 4;client qui se déconnecte
    joueur_nombre=joueur_nombre-1
    value=cherche_sock(EventClient())
    Joueur(value)\compte_sock=0
  EndSelect
Until quitter=1
CloseNetworkServer(0)
EndIf
EndProcedure
Et ce système traite les données ;

Code : Tout sélectionner

Procedure traitement(*s)
*my = AllocateMemory(2000)
CopyMemory(*s+6,*my,2000)
FreeMemory(*s)
JoueurNET=joueuralpha
UnlockMutex(traite)
ID = PeekB(*my)
Sock=cherche_sock(JoueurNET)
Debug "donné recus ; "+Str(ID)

*free=*my
*my+1
  Select ID
    Case 1 ;un joueur quitte le serveur !
      sock=cherche_sock(JoueurNET)
      monde$=Joueur(sock)\position_map
      pseudo.s=Joueur(sock)\compte_pseudo
      yy=Joueur(sock)\position_y
      xx=Joueur(sock)\position_x
      GetHttp("http://kraessor.free.fr/GAME/set_deplacement.php?monde="+monde$+"&x="+Str(xx)+"&y="+Str(yy)+"&name="+pseudo+"&hauteur=0")
    Case 3 ;connection au serveur d'un nouveau joueur
    
      nomperso$=PeekS(*my);pseudo
      Joueur(Sock)\compte_pseudo=nomperso$
      *my=*my+MemoryStringLength(*my)+1
      PeekS(*my);version du client-inutile pour le moment peut etre supprimer ?
      site$="http://kraessor.free.fr/GAME/"
      
      ;chargement des principals informations concernant le compte du joueur
      Joueur(Sock)\compte_pseudo=nomperso$
      Joueur(Sock)\compte_id=Val(GetHttp(site$+"info.php?alpha=id&pseudo="+nomperso$))
      joueurid=Joueur(Sock)\compte_id
      Joueur(Sock)\position_map=GetHttp(site$+"info.php?alpha=niveau&id="+Str(joueurid))
      Joueur(Sock)\position_x=Val(GetHttp(site$+"info.php?alpha=x&id="+Str(joueurid)))
      Joueur(Sock)\position_y=Val(GetHttp(site$+"info.php?alpha=y&id="+Str(joueurid)))
      compte_silver$=GetHttp(site$+"info_compte.php?alpha=silver&id="+Str(joueurid))
      
      ;compte silver système
      If compte_silver$<>"" And compte_silver$<>"non" 
      Joueur(Sock)\compte_niveau="oui"
      Else
      Joueur(Sock)\compte_niveau="non"
      EndIf
      
      ;envoie d'un message pour configuré le joueur au départ   
      *buffer=AllocateMemory(2000)
      *pointeur=*buffer
      *pointeur+1
      PokeB(*pointeur,5)
      *pointeur+1
      PokeB(*pointeur,5)
      *pointeur+1
      info$="position_set("+Str(Joueur(Sock)\position_x)+","
      info$+Str(Joueur(Sock)\position_y)+",'"+Joueur(Sock)\position_map+"');"
      info$+"info_set('"+Str(Joueur(Sock)\compte_id)+"','"+Joueur(Sock)\compte_niveau+"');"
      PokeS(*pointeur,info$)
      SendNetworkData(JoueurNET, *buffer, 2000)
      alpha+1
      FreeMemory(*buffer)
      
      *buffer=AllocateMemory(2000)      
      ;envoie d'un message pour popup de départ
      *pointeur=*buffer
      PokeB(*pointeur,8)
      *pointeur+1
      PokeB(*pointeur,1)
      *pointeur+1
      draw$="draw_text(x+5,y+20,'Décembre arrive à Blendra##Et oui, lhiver est arrivé,#La météo est donc passé au blanc#La temperature a chutée');";
      PokeS(*pointeur,"Nouveauté")
      *pointeur+MemoryStringLength(*pointeur)
      PokeS(*pointeur,draw$)
      *pointeur+MemoryStringLength(*pointeur)
      PokeS(*pointeur,"")
      *pointeur+MemoryStringLength(*pointeur)
      SendNetworkData(JoueurNET,*buffer,MemorySize(*buffer))
      
    Case 4 ;un joueur parle dans le chat
      message$=PeekS(*my)
      Debug "message reçus"
      sock=cherche_sock(JoueurNET)
      Debug "ID ; "+Str(sock)
      pseudo.s=Joueur(sock)\compte_pseudo
      map.s=Joueur(sock)\position_map
      alpha=0
      *buffer=AllocateMemory(2000)
      *pointeur=*buffer
      *pointeur+1
      PokeB(*pointeur,7)
      *pointeur+1
      PokeB(*pointeur,7)
      *pointeur+1
      PokeS(*pointeur,pseudo+" : "+message$)
      Debug pseudo+" : "+message$
      Repeat
        If Joueur(alpha)\position_map=map And Joueur(alpha)\compte_sock<>0
          SendNetworkData(Joueur(alpha)\compte_sock, *buffer, 2000)
          Debug alpha
        EndIf
      alpha+1
      Until alpha=5000
      FreeMemory(*buffer)
  EndSelect
EndProcedure
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Alors je vois 2 choses qui peuvent potentiellement créer le problème dont tu parles :

1. Le LockMutex qui n'est pas opérationnel lorsque l'on veut bloquer le programme principal. J'ai eu le même souci sur un projet réseau et j'ai trouvé mon bonheur ici : http://www.purebasic.fr/french/viewtopi ... =lockmutex. D'ailleurs merci à lionel_om pour sa solution. Je pense que ça peut régler ton problème.

2. La seconde chose c'est le ReceiveNetworkData(EventClient(),*s+4,1000). Si ta requête fait plus de 1000 octets, une partie du paquet va passer à la poubelle. Je te conseille quelque chose dans ce gout là (non testé) :

Code : Tout sélectionner

#buffer_length = 1000


total_lus.l = 0
Repeat

  octets_lus.l = ReceiveNetworkData(EventClient(), *s, #buffer_length)
  total_lus + octets_lus
  *s + octets_lus
Until octets_lus = #buffer_length

; Replace le pointeur au début de la zone mémoire
*s - total_lus


Il faudrait également tester la taille de la mémoire allouée en fonction de la taille du paquet envoyé, mais dans ton cas ça ne doit pas être le souci je pense.

En espérant que cela pourra t'aider,
Cls[/code]
Anonyme

Message par Anonyme »

j'ai pas tout lu , mais en temporisant l'envois de message ? car si tu bombarde la bande passante de message a chaque boucle , ca ne va pas.

Le serveur ecoute en temps réel , et met dans la pile les messages recu , tu les traite à ton rythme. il réponds aux clients suivant les infos qu'il reçois.
il envois des réponses tout les 50 / 75 ms et pas à chaque boucle. ( Change le temps suivant les résultat )

les clients , envois des données au serveur et en reçois en temps réel , idem que pour le serveur , il est inutile , même en "threadant" , d'envoyer des messages en temps réel , temporise tout les 50 / 75 ms.

sa ira beaucoup mieux après à mon avis.
stombretrooper
Messages : 117
Inscription : dim. 21/déc./2008 18:39

Message par stombretrooper »

:) Avec la temporisation c'est mieux mais j'ai encore des messages qui n'arrivent pas mais beaucoup moins c'est sur :)
Répondre