Problème réseau

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Problème réseau

Message par Aranoth »

Salut,

j'ai essayé de faire marcher un dialogue entre PC, à 2J ca marche nickel, ils s'échange les infos correctement, mais le troisième joueur ne marche pas (et tous ceux qui suivent non plus) !

Il n'envoie aucun message au serveur, ne répond pas quand on lui parle, etc...(en essayant sur un meme PC)

Je post mon code, si vous voyez une erreure ou des trucs a optimiser:

Code : Tout sélectionner

; --------------------------------------------
;              EXEMPLE RESEAU
;           Un dialogue efficace
; --------------------------------------------

;- Initialisation de DirectX
InitNetwork()
InitSprite()

;- Activation des plugins et fonctions à déclarer
UsePNGImageDecoder()
Declare.l GetPlayer(clientid)

;- Variables
Title$="Un dialogue Efficace"
Flag= #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SystemMenu 
Win_X=640
Win_Y=480
#Win=0
IP$="127.0.0.7"
Port = 6832
*Buffer = AllocateMemory(1000)
ID=1

;- Ouverture de la fenetre
;OpenWindow(#Win,0,0,Win_X,Win_Y,Flag,Title$)
;OpenWindowedScreen(WindowID(#Win),0,0,Win_X,Win_Y,0,0,0)

;- Liste des joueurs
Structure Player
  id.l
  client.l
  nom.s
  x.l
  y.l
  pck.s
  flag.l
EndStructure
NewList Player.Player()

;- Choix entre HOST et CLIENT

Nom$=InputRequester(Title$,"Votre nom ?","")
Choix:
CHOIX$=InputRequester(Title$,"HOST ou CLIENT","HOST")
Message$=InputRequester(Title$,"Votre message ?","")

;- Choix Host
If CHOIX$="HOST"

  AddElement(Player())
  Player()\id=1
  Player()\nom=Nom$
  Player()\pck=Message$
  Player()\flag=1
  
  ;Creer la partie
  CreateNetworkServer(Port)
  ;Boucle
  Repeat
    ;Recupère les infos Event
    SEvent = NetworkServerEvent()
    If SEvent
      ;Recupère le client qui envoie
      ClientID = NetworkClientID()
      ;Utilise un select
      Select SEvent
      
        Case 1  ;Un client se connecte
          MessageRequester(Title$, "Un client s'est connecté !", 0)
          ;Ajoute un element dans la liste
          AddElement(Player())
            Player()\client=ClientID
            Player()\id=ID
            Player()\flag=0
            ID=ID+1
          Debug "Le client n°"+Str(Player()\id)+", a été ajouté !"
  
        Case 2  ;Un client envoie des data
          FreeMemory(*Buffer)
          *Buffer = AllocateMemory(1000) 
          ReceiveNetworkData(ClientID, *Buffer, 1000)
          Msg$=PeekS(*Buffer)
          ;Si c'est la 1ere fois qu'il parle
          If StringField(Msg$,1,"*")="0"
            SelectElement(Player(),GetPlayer(ClientID))
            ;On prend son nom
            Player()\nom=StringField(Msg$,2,"*")
            Player()\pck=StringField(Msg$,3,"*")
            Player()\flag=1            
            flag=1
          ;Sinon
          Else
            SelectElement(Player(),GetPlayer(ClientID))
            ;On regarde ce qu'il a à dire
            Player()\pck=StringField(Msg$,2,"*")
            Debug Player()\nom +" send: "+Msg$
            flag=0             
          EndIf
            ;On informe le client de ce qui se passe (=on répond)
            For j=0 To CountList(Player())-1
              SelectElement(Player(),j)
              If j=0
                ;Si c'est nos propres infos, on les mets à jour
                MsgToSend$=Str(flag)+"*"+Str(j)+"*"+Str(Player()\client)+"*"+Player()\nom+"*"+Message$+"*"
              Else
                ;Sinon on envoie ce qu'on a                
                MsgToSend$=Str(flag)+"*"+Str(j)+"*"+Str(Player()\client)+"*"+Player()\nom+"*"+Player()\pck+"*"
              EndIf
              Debug "Send: "+MsgToSend$
              SendNetworkString(ClientID,MsgToSend$)     
            Next j
          ;Debug "String: "+Msg$
  
        Case 3  ;Un client envoie un fichier
          MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has send a file via the network !", 0)
          ReceiveNetworkFile(ClientID, "C:\TEST_Network.txt")
  
        Case 4  ;Un client se déconnecte
          SelectElement(Player(),GetPlayer(ClientID))
          MessageRequester(Title$, Player()\nom+" s'est déconnecté !", 0)
          ;On supprime son element
          DeleteElement(Player())
          FirstElement(Player())    
          
      EndSelect
    EndIf
    ;Rattrapage, si le joueur n'a rien envoyé automatiquement
    For x=0 To CountList(Player())-1
      SelectElement(Player(),x)
      If Player()\flag=0
        ;On l'aborde
        SendNetworkString(Player()\client,"Reveille toi !")
        Debug "Rattrapage !"
      EndIf
    Next x

  Until DO=1

;- Choix Client
ElseIf CHOIX$="CLIENT"
  ;Rejoind la partie
  ConnectionID = OpenNetworkConnection(IP$,Port)
  ;Donne notre nom et lance le processus de discution (ce message est le déclancheur)
  SendNetworkString(ConnectionID,"0*"+Nom$+"*"+Message$+"*")
 ;Boucle
  Repeat
    ;Recupère les infos Event
    SEvent = NetworkClientEvent(ConnectionID)
    If SEvent
      ;Utilise un select
      Select SEvent
     
        Case 2  ;le serveur envoie des data
          FreeMemory(*Buffer)
          *Buffer = AllocateMemory(1000) 
          ReceiveNetworkData(ConnectionID,*Buffer, 1000)
          Msg$=PeekS(*Buffer)
          ;On trie les infos que le serveur à envoyé
          ClientID=Val(StringField(Msg$,2,"*"))
            flag=Val(StringField(Msg$,1,"*"))
            If flag=1
              ;Si on n'avais encore jamais rencontré ce joueur on lui créer un élément
              AddElement(Player())
              Player()\client=Val(StringField(Msg$,3,"*"))
              Player()\nom=StringField(Msg$,4,"*")
              Player()\pck=StringField(Msg$,5,"*")
              Debug "UN NOUVEAU JOUEUR A ETE CREER"
            Else
              ;Bah sinon on met à jour ses infos
              SelectElement(Player(),GetPlayer(ClientID))
              Player()\pck=StringField(Msg$,5,"*")        
            EndIf   
            Debug Player()\nom +" dit: "+Player()\pck   
          ;Et on répond
            SendNetworkString(ConnectionID,"1*"+Message$+"*")          
  
        Case 3  ;le serveur envoie un fichier
          MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has send a file via the network !", 0)
          ReceiveNetworkFile(ClientID, "C:\TEST_Network.txt")
          
    
      EndSelect
    EndIf

  Until DO=1


;- Choix Erreur
Else
  MessageRequester(Title$,"Tappez HOST ou CLIENT !")
  Goto Choix
EndIf

;Trouve l'ID du joueur (l'ID de l'élement en fait) grace à son ClientID
Procedure.l GetPlayer(clientid)
  For x=0 To CountList(Player())-1
    SelectElement(Player(),x)
    If Player()\client=clientid
      Break
    EndIf
  Next x
  ProcedureReturn x
EndProcedure
merci :wink: [/quote]
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

n'y a t'il personne qui trouve le problème ?
ca me bloque baucoup :cry:

Comtois a l'air de se débrouiller maintenant en réseau...pourrait il examiner ca ? :wink:
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
julien
Messages : 846
Inscription : ven. 30/janv./2004 15:06
Contact :

Message par julien »

J'ai lu ton code source en diag...
C'est que ton serveur est occupé avec le client 1 ?!
Utilise les Threads pour chaque client :)
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

les Threads ? je connais pas, tu peut m'en dire plus stp ?
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
julien
Messages : 846
Inscription : ven. 30/janv./2004 15:06
Contact :

Message par julien »

"Un thread est une partie d'un programme qui peut être lancée de manière asynchrone en arrière plan du programme. Cela signifie qu'il est possible d'effectuer certaines opérations longues (compress, image processing...) sans interrompre l'ensemble du programme, et de laisser ainsi l'utilisateur effectuer d'autres tâches. Un thread s'exécute à l'intérieur du programme, il ne s'agit pas d'un autre processus. Lorsque le programme se termine, tous les threads sont détruits. Sous PureBasic, les threads sont des procédures appelées de manière asynchrone. Un thread tourne jusqu'à ce que la procédure se termine. "
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

ok
donc faut que je mette chaque gestion de joueur dans une procedure et lancer ca comme thread ?

merci :wink:
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
Ombres
Messages : 51
Inscription : sam. 24/janv./2004 12:46
Contact :

Message par Ombres »

Normalement ca devrai marcher sans thread ...
Quand je lance le client (meme le 1er), j'ai un probleme a la ligne
Player()\pck=StringField(Msg$,5,"*") / Pointer is null

J'ai simplifié un peu les boucles sur les liste chainées et enlevé les messagerequester qui pouvaient bloquer le programme:

Code : Tout sélectionner

; -------------------------------------------- 
;              EXEMPLE RESEAU 
;           Un dialogue efficace 
; -------------------------------------------- 

;- Initialisation de DirectX 
InitNetwork() 
InitSprite() 

;- Activation des plugins et fonctions à déclarer 
UsePNGImageDecoder() 
Declare.l GetPlayer(clientid) 

;- Variables 
Title$="Un dialogue Efficace" 
Flag= #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SystemMenu 
Win_X=640 
Win_Y=480 
#Win=0 
IP$="127.0.0.7" 
Port = 6832 
*Buffer = AllocateMemory(1000) 
ID=1 

;- Ouverture de la fenetre 
;OpenWindow(#Win,0,0,Win_X,Win_Y,Flag,Title$) 
;OpenWindowedScreen(WindowID(#Win),0,0,Win_X,Win_Y,0,0,0) 

;- Liste des joueurs 
Structure Player 
  id.l 
  client.l 
  nom.s 
  x.l 
  y.l 
  pck.s 
  flag.l 
EndStructure 
NewList Player.Player() 

;- Choix entre HOST et CLIENT 

Nom$=InputRequester(Title$,"Votre nom ?","") 
Choix: 
CHOIX$=InputRequester(Title$,"HOST ou CLIENT","HOST") 
Message$=InputRequester(Title$,"Votre message ?","") 

;- Choix Host 
If CHOIX$="HOST" 

  AddElement(Player()) 
  Player()\id=1 
  Player()\nom=Nom$ 
  Player()\pck=Message$ 
  Player()\flag=1 
  
  ;Creer la partie 
  CreateNetworkServer(Port) 
  ;Boucle 
  Repeat 
    ;Recupère les infos Event 
    SEvent = NetworkServerEvent() 
    If SEvent 
      ;Recupère le client qui envoie 
      ClientID = NetworkClientID() 
      ;Utilise un select 
      Select SEvent 
      
        Case 1  ;Un client se connecte 
          Debug  "Un client s'est connecté !"
          ;Ajoute un element dans la liste 
          AddElement(Player()) 
            Player()\client=ClientID 
            Player()\id=ID 
            Player()\flag=0 
            ID=ID+1 
          Debug "Le client n°"+Str(Player()\id)+", a été ajouté !" 
  
        Case 2  ;Un client envoie des data 
          FreeMemory(*Buffer) 
          *Buffer = AllocateMemory(1000) 
          ReceiveNetworkData(ClientID, *Buffer, 1000) 
          Msg$=PeekS(*Buffer) 
          ;Si c'est la 1ere fois qu'il parle 
          If StringField(Msg$,1,"*")="0" 
            GetPlayer(ClientID)
            ;On prend son nom 
            Player()\nom=StringField(Msg$,2,"*") 
            Player()\pck=StringField(Msg$,3,"*") 
            Player()\flag=1            
            flag=1 
          ;Sinon 
          Else 
            GetPlayer(ClientID)
            ;On regarde ce qu'il a à dire 
            Player()\pck=StringField(Msg$,2,"*") 
            Debug Player()\nom +" send: "+Msg$ 
            flag=0              
          EndIf 
            ;On informe le client de ce qui se passe (=on répond) 
            ForEach Player()
              j=ListIndex(Player())
              If j=0 
                ;Si c'est nos propres infos, on les mets à jour 
                MsgToSend$=Str(flag)+"*"+Str(j)+"*"+Str(Player()\client)+"*"+Player()\nom+"*"+Message$+"*" 
              Else 
                ;Sinon on envoie ce qu'on a                
                MsgToSend$=Str(flag)+"*"+Str(j)+"*"+Str(Player()\client)+"*"+Player()\nom+"*"+Player()\pck+"*" 
              EndIf 
              Debug "Send: "+MsgToSend$ 
              SendNetworkString(ClientID,MsgToSend$)      
            Next
          ;Debug "String: "+Msg$ 
  
        Case 3  ;Un client envoie un fichier 
          Debug "Client "+Str(ClientID)+" has send a file via the network !"
          ReceiveNetworkFile(ClientID, "C:\TEST_Network.txt") 
        Case 4  ;Un client se déconnecte 
          GetPlayer(ClientID) 
          Debug Player()\nom+" s'est déconnecté !"
          ;On supprime son element 
          DeleteElement(Player())  
      EndSelect 
    EndIf 
    ;Rattrapage, si le joueur n'a rien envoyé automatiquement 
    ForEach Player()
      If Player()\flag=0
        ;On l'aborde
        SendNetworkString(Player()\client,"Reveille toi !") 
        Debug "Rattrapage !" 
      EndIf 
    Next

  Until DO=1 

;- Choix Client 
ElseIf CHOIX$="CLIENT" 
  ;Rejoind la partie 
  ConnectionID = OpenNetworkConnection(IP$,Port) 
  ;Donne notre nom et lance le processus de discution (ce message est le déclancheur) 
  SendNetworkString(ConnectionID,"0*"+Nom$+"*"+Message$+"*") 
 ;Boucle 
  Repeat 
    ;Recupère les infos Event 
    SEvent = NetworkClientEvent(ConnectionID) 
    If SEvent 
      ;Utilise un select 
      Select SEvent 
      
        Case 2  ;le serveur envoie des data 
          FreeMemory(*Buffer) 
          *Buffer = AllocateMemory(1000) 
          ReceiveNetworkData(ConnectionID,*Buffer, 1000) 
          Msg$=PeekS(*Buffer) 
          ;On trie les infos que le serveur à envoyé 
          ClientID=Val(StringField(Msg$,2,"*")) 
            flag=Val(StringField(Msg$,1,"*")) 
            If flag=1 
              ;Si on n'avais encore jamais rencontré ce joueur on lui créer un élément 
              AddElement(Player()) 
              Player()\client=Val(StringField(Msg$,3,"*")) 
              Player()\nom=StringField(Msg$,4,"*") 
              Player()\pck=StringField(Msg$,5,"*") 
              Debug "UN NOUVEAU JOUEUR A ETE CREER" 
            Else 
              ;Bah sinon on met à jour ses infos 
              GetPlayer(ClientID)
              ;SelectElement(Player(),GetPlayer(ClientID)) 
              Player()\pck=StringField(Msg$,5,"*")        
            EndIf    
            Debug Player()\nom +" dit: "+Player()\pck    
          ;Et on répond 
            SendNetworkString(ConnectionID,"1*"+Message$+"*")          
  
        Case 3  ;le serveur envoie un fichier 
          Debug "Client "+Str(ClientID)+" has send a file via the network !"
          ReceiveNetworkFile(ClientID, "C:\TEST_Network.txt") 
          
    
      EndSelect 
    EndIf 

  Until DO=1 


;- Choix Erreur 
Else 
  MessageRequester(Title$,"Tappez HOST ou CLIENT !") 
  Goto Choix 
EndIf 

;Trouve l'ID du joueur (l'ID de l'élement en fait) grace à son ClientID 
Procedure.l GetPlayer(clientid) 
  ForEach Player()
    If Player()\client=clientid 
      ProcedureReturn
    EndIf 
  Next
EndProcedure
J'ai pas le temps de voir d'ou viens le probleme pour le moment :(
julien
Messages : 846
Inscription : ven. 30/janv./2004 15:06
Contact :

Message par julien »

Voici un petit exemple pour comprendre l'avantage des threads, il te permette de faire plusieurs action en même temps sans bloquer le programme


Code : Tout sélectionner

Procedure son_continue()
Repeat
Delay(100)
Beep_(150,100)
ForEver
EndProcedure


Procedure son_continue2()
Repeat
Delay(1000)
Beep_(500,200)
ForEver
EndProcedure







CreateThread(@son_continue(),0) ; lance le thread 1
CreateThread(@son_continue2(),0); lance le thread 2




Repeat
Delay(10)
ForEver
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

donc ca lance 2 boucles en meme temps :P
ah ouais pratique :wink:

Pour Ombres >> si il met pointer is null c surement car la valeure ="", je sais pas d'où ca peut venir, mais merci pour l'optimisation de la procedure :wink:
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
Ombres
Messages : 51
Inscription : sam. 24/janv./2004 12:46
Contact :

Message par Ombres »

Le probleme de pointeur viens de la liste chainée Player() qui doit être vide ... jverrai ca demain...
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

je verrai aussi ca demain, merci a vous pour vos réponses :wink:
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

dans mon cas il faut donc que je fasse:

Code : Tout sélectionner

procedure blabla(client)
  tout le bazarre de reception des données et d'envoie
  le dialogue quoi
endprocedure

repeat

select evenement réseau

case 1 (connexion)
  creer le thread pour le joueur concerné

case 3 (deconnexion)
  detruire le thread

endselect

until do=1
c'est ca ? mais n'y aura t'il pas de problème niveau variables ou chaines, par exemple le *Buffer sera utilisé simultanément, ainsi que les chaines dont l'élement selectionné va changer en meme temps, il n'y aura aucuns problèmes de ce coté, où faut t'il prévoir qq chose ?

merci
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
Ombres
Messages : 51
Inscription : sam. 24/janv./2004 12:46
Contact :

Message par Ombres »

Oui il faut prévoir quelquechose si tu veux utiliser des threads...

Si t'as envie de lire une dixaines de page ya ca :roll: :
http://bob.developpez.com/tutapiwin/article_46.php

Sinon ya une userlib pour pb qui m'a l'air assez simple à utiliser:
http://www.purearea.net/pb/download/use ... adSync.zip
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message par Aranoth »

ah ouais c'est bien la galère, enfin la lib à l'air de bien aider d'après ce que je vois sur dev.com :)

je vais essayer de me débrouiller avec ca :?
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
Avatar de l’utilisateur
cederavic
Messages : 1338
Inscription : lun. 09/févr./2004 23:38
Localisation : Bordeaux

Message par cederavic »

Répondre