Page 1 sur 1
Serveur ; pertes de données
Publié : lun. 22/déc./2008 19:14
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 ?

Publié : lun. 22/déc./2008 19:23
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 !).
Publié : lun. 22/déc./2008 19:33
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
Publié : lun. 22/déc./2008 19:44
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

)
Publié : lun. 22/déc./2008 21:16
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
Publié : lun. 22/déc./2008 22:07
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]
Publié : lun. 22/déc./2008 22:23
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.
Publié : mar. 23/déc./2008 14:14
par stombretrooper

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