Page 1 sur 1

Network : transfert très lent (lag)

Publié : sam. 04/mars/2006 18:37
par Dionyzos
Bonjour,

J'ai pondu un petit exemple de code pour piloter à distance des actions entre un client et un server ; cela pourra peut-etre servir à qq'un qui débute avec la lib NetWork.

Le code ce lance en ligne de commande avec en paramètre le mode d'execution (client ou server), et l'adresse IP distante.
Ex.:

Code : Tout sélectionner

prog.exe -client 192.168.0.1
dans cette exemple vous lancer le programme en mode "client" et vous vous connectez au serveur dont l'IP est 192.168.0.1.
ATTENTION : sur le PC 192.168.0.1 le programme doit être lancer en mode "server" avant le client.

Voici le code :

Code : Tout sélectionner

#WIN=0
#COTE=50

Global x,y,param.s, cnxID,IP.s
x = 0
y = 0
param = ProgramParameter()
IP = ProgramParameter()

InitSprite()
InitKeyboard()
InitNetwork()
port=6666
 

If param = "-server"
  Buffer = AllocateMemory(500)
  CreateNetworkServer(Port)
ElseIf param = "-client"
  cnxID = OpenNetworkConnection(IP,port)
  If cnxID = 0
    MessageRequester("Erreur","Serveur "+Str(IP)+" introuvable !", #PB_MessageRequester_Ok)
  EndIf
Else

EndIf


Procedure MoveSquare(valeur)
  Select valeur
    Case 0
      x-10
      If x < 0 : x = 0 : EndIf
    Case 1
      x+10
      If x > 640-#COTE : x = 640-#COTE : EndIf
    Case 2
      y-10
      If y < 0 : y = 0 : EndIf
    Case 3
      y+10
      If y > 480-#COTE : y = 480-#COTE : EndIf
  EndSelect
  
  If param = "-client"
    SendNetworkString(cnxID, Str(x)+";"+Str(y)+";")
  EndIf
  
EndProcedure


OpenWindow(#WIN,0,0,640,480,#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget,"test transfert data")
OpenWindowedScreen(WindowID(#WIN),0,0,640,480,0,0,0)

Repeat
  EventID = WindowEvent()
  ClearScreen(0,0,0)
  StartDrawing(ScreenOutput())
  Box(x,y,#COTE,#COTE,RGB(255,0,0))
  StopDrawing()
  FlipBuffers()
  
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Left)  : MoveSquare(0) : EndIf
  If KeyboardPushed(#PB_Key_Right) : MoveSquare(1) : EndIf
  If KeyboardPushed(#PB_Key_Up)    : MoveSquare(2) : EndIf
  If KeyboardPushed(#PB_Key_Down)  : MoveSquare(3) : EndIf  
  Delay(1)

  If param = "-server"
    SEvent = NetworkServerEvent()
    If SEvent = 2
      clientID = NetworkClientID()
      ReceiveNetworkData(clientID, Buffer, 500)
      packet.s = PeekS(Buffer,MemoryStringLength(Buffer))
      x = Val(StringField(packet,1,";"))
      y = Val(StringField(packet,2,";"))
    EndIf
  EndIf


Until EventID = #PB_Event_CloseWindow

If param = "-server"
  CloseNetworkServer()
ElseIf param = "-client"
  CloseNetworkConnection(cnxID)
EndIf

End
L'utilisation est simple : vous déplacez via les fleches du clavier le carré rouge sur l'écran CLIENT, et il doit normalement se déplacer aux mêmes coordonnées sur l'écran SERVER.

Ca marche, mais c'est super lent. J'ai de gros lags.

Qq'un, qui maitrise mieux la lib Network que moi, pourrait me donner une petit astuce ou deux pour améliorer ce lag ?
:?

Merci d'avance :)

Publié : sam. 04/mars/2006 20:12
par nico
C'est clair que niveau démo, c'est pas terrible!

Publié : sam. 04/mars/2006 20:15
par Dionyzos
nico a écrit :C'est clair que niveau démo, c'est pas terrible!
Merci, nico, ca fait vachemant avancer le schmilblick... :roll:

Publié : sam. 04/mars/2006 23:33
par Heis Spiter
A première vu, il me semble que le ralentissement ne vient pas de la partie Network. Il est difficile de faire plus optimisé. Maintenant, on pourrait imaginer une méthode plus rapide évitant le passage par les chaînes.

Une remarque d'ordre général, pour éviter quelques soucis :

Code : Tout sélectionner

*Buffer = AllocateMemory(512)
ReceiveNetworkData(clientID, *Buffer, 500) 
packet.s = PeekS(Buffer,MemoryStringLength(*Buffer))
FreeMemory(*Buffer)
C'est pas grand chose, mais c'est nécessaire ;).

Publié : dim. 05/mars/2006 12:14
par Dionyzos
Merci Heis Spiter pour ta réponse. :D

J'ai changé mon code comme tu me l'as suggéré, mais ça n'a pas changé grand chose, voire rien du tout :(

Par contre j'ai remarqué qu'avec un SendNetworkData() au lieu d'un SendNetworkString(), le serveur reçoit dans la paquet IP plus de une coordonnée à la fois.
un coup il en reçoit 5, puis 12, puis 1, puis 26,...

Cela dépend apparemment de l'appui plus ou moins long sur les directions côté client :
si le client appuie longtemps, le server reçoit beaucoup de coordonnées,
si le client appuie brièvement, peu de coordonnées sont envoyées (1 minimum)

Partant de cette observation je créé une boucle supplémentaire qui affiche le carré pour toutes les coordonnées du paquet, avant de passer au suivant.

Voici la nouvelle version du code (que j'ai ultra commenté pour ceux qui voudraient le réutiliser) :

Code : Tout sélectionner

#WIN  = 0   ; ID de la fenêtre principale
#COTE = 50  ; taille des côtés du carré
#STEP = 2   ; nombre de pixels de déplacement par pas

;Déclaration des variables globales
Global x, y, mode.s, IP.s, cnxID

x = 0 ; initialisation de x à 0
y = 0 ; initialisation de y à 0

mode = ProgramParameter() ; récupération du 1er paramètre de la ligne de commande
IP   = ProgramParameter() ; récupération du 2eme paramètre...

InitSprite()    ; initialisation de la bilbiothèque des sprites
InitKeyboard()  ; initialisation de la bilbiothèque du clavier
InitNetwork()   ; initialisation de la bilbiothèque du réseau

port=6666 ; Attribution du port 6666 au programme


If mode = "-server"

  ;si le prog est en mode "server", alors lancer le server 
  CreateNetworkServer(Port)  

ElseIf mode = "-client"

  ;si le prog est en mode "client", alors ouvrir la connexion client sur le server
  cnxID = OpenNetworkConnection(IP,port)

  ;si la connexion ne s'est pas faite, alors afficher le message suivant :
  If cnxID = 0
    MessageRequester("Erreur","Serveur "+IP+" introuvable !", #PB_MessageRequester_Ok)
  EndIf

EndIf


Procedure MoveSquare(direction)
;********************************************************************************
; Déplace les coordonnées du carré rouge en fonction de la direction renvoyée
; par la variable 'direction'.
; 0=gauche, 1=droite, 2=haut, 3=bas
;********************************************************************************

  Select direction
    Case 0 ; gauche
      x-#STEP
      If x < 0 : x = 0 : EndIf                 ; empêche le carré de sortir de l'écran (à gauche)
    Case 1 ; droite
      x+#STEP
      If x > 640-#COTE : x = 640-#COTE : EndIf ; empêche le carré de sortir de l'écran (à droite)
    Case 2 ; haut
      y-#STEP
      If y < 0 : y = 0 : EndIf                 ; empêche le carré de sortir de l'écran (en haut)
    Case 3 ; bas
      y+#STEP
      If y > 480-#COTE : y = 480-#COTE : EndIf ; empêche le carré de sortir de l'écran (en bas)
  EndSelect
  
  ;SI le prog est en mode "client", ALORS envoi des coordonnées X & Y au server
  ;X & Y sont séparés par des ";" et les différents blocs de coordonnées sont séparés par des "#"
  If mode = "-client"
    packet.s = Str(x)+";"+Str(y)+"#"
    SendNetworkData(cnxID,@packet,Len(packet))
  EndIf
  
EndProcedure


Procedure DisplaySquare()
;********************************************************************************
; Affiche le carré rouge à l'écran
;********************************************************************************

  ClearScreen(0,0,0)                  ; Efface l'écran avec une couleur de fond noire
  StartDrawing(ScreenOutput())        ; démarre la fonction "dessiner sur l'écran"
  Box(x,y,#COTE,#COTE,RGB(255,0,0))   ; dessine le carré rouge aux coordonnées x & y
  StopDrawing()                       ; arrête la fonction "dessiner sur l'écran"
  FlipBuffers()                       ; affiche le résultat du dessin (permute les buffers)

EndProcedure


OpenWindow(#WIN,0,0,640,480,#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget,"test transfert data")
OpenWindowedScreen(WindowID(#WIN),0,0,640,480,0,0,0)

ssbloc.s="" ; initialisation de la chaine 'ssbloc'

;Boucle principale répétée jusqu'a ce que la fenêtre soit fermée
Repeat

  EventID = WindowEvent() ; vérifie si un évènement Windows a été activé

  DisplaySquare()  ; affiche le carré rouge

  ExamineKeyboard() ; vérifie si une touche du clavier a été enfoncée puis relâchée

  If KeyboardPushed(#PB_Key_Left)  : MoveSquare(0) : EndIf
  If KeyboardPushed(#PB_Key_Right) : MoveSquare(1) : EndIf
  If KeyboardPushed(#PB_Key_Up)    : MoveSquare(2) : EndIf
  If KeyboardPushed(#PB_Key_Down)  : MoveSquare(3) : EndIf  

  ;SI le prog a été lancé avec le mode "server", et qu'il n'y a pas de bloc...
  If mode = "-server" And bloc = 0

    SEvent = NetworkServerEvent() ; vérifie si des packets IP ont été recus

    If SEvent = 2 ; (2 = réception de données brutes)
      
      ;Récupération de l'ID client
      clientID = NetworkClientID()
      
      ;Alloue 512 octets dans la mémoire pour le buffer de réception
      *buffer = AllocateMemory(512)
      
      ;Récupère les données recues, et les place dans le buffer
      ReceiveNetworkData(clientID, *buffer, 500)
      
      ;Renvoie dans la varaible 'packet' la chaine contenue dans le buffer 
      packet.s = PeekS(*buffer,MemoryStringLength(*buffer))
      
      ;Compte le nombre de bloc de coordonnées
      bloc = CountString(packet,"#")
      
      ;Supprime le buffer
      FreeMemory(*buffer)
    EndIf
  EndIf
  
  ;SI il y a au moins un bloc, ALORS faire la bloucle qui récupère les coordonnées de chaque bloc
  If bloc > 0
    For k=1 To bloc
      ssbloc = StringField(packet,k,"#")  ; extrait le bloc numéro k
      x = Val(StringField(ssbloc,1,";"))  ; change x avec la coordonnée X du bloc k
      y = Val(StringField(ssbloc,2,";"))  ; change y avec la coordonnée Y du bloc k
      DisplaySquare()                     ; Affiche le carré rouge
      Delay(1)                            ; petit délai de 1 milliseconde pour libérer le CPU
    Next
    bloc=0 ; une fois la boucle terminée -> réinitialisation du compteur de blocs à 0
  EndIf

  Delay(1)

Until EventID = #PB_Event_CloseWindow

If mode = "-server"
  CloseNetworkServer()            ; si le prog est en mode "server", alors fermer le server
ElseIf mode = "-client"
  CloseNetworkConnection(cnxID)   ; si le prog est en mode "client", alors fermer la connexion client
EndIf


End ; Terminaison du programme.
Maintenant je ne lag plus (c’est fluide), mais il y a un assez gros décalage dans le temps au niveau du mouvement.

Donc j’ai déplacé le problème plutôt que le carré rouge ;)

Si qq’un a encore d’autres idées, il est le bienvenu :)

Publié : dim. 05/mars/2006 12:37
par Sami
C'est normal que tu est ce problème. Pour ne plus l'avoir, il faut implanter un systéme de prédiction de mouvement. Le principe est simple mais son implantation est plutôt difficile.
Il faut prendre les coordonnées de ton carré rouge tout les 1/25 secondes par exemple. Du coté de ton client cela se traduit par un envoi de paquets tout les 1/25 de secondes. Cela permet d'économiser la bande passante.
Du coté serveur, il faut que tu interpole entre les coordonnées que tu recoit et les coordonnées précédentes pour gérer un mouvement fluide.

C'est la base des jeux de type FPS. Il faut implanter un modéle de gestion de déplacement en partant du principe de Newton en mécanique général.
La formule de base est la suivante masse * accélération = Somme des forces sur ton carré rouge.

Pour limiter la taille des paquets, on peut aussi les compresser via un algo. Mais dans ce cas je ne pense pas que ce soit nécessaire.

Publié : dim. 05/mars/2006 13:42
par Dionyzos
ooouUUAAAAAOOUUUUuuuu ! 8O

T'as réponse est parfaite Sami, et je sais pas pourquoi, mais je sens que je vais en chier grave pour l'implémenter.
#jaune

C'est là qu'on voit la différence entre un vrai développeur et un mec comme moi qui tatonne :roll:
Je vais devoir faire appel à toutes mes capacités scientifiques pour m'en sortir #hydro

Merci, enore, je commence à y reflechir ;)

Publié : lun. 06/mars/2006 0:54
par Anonyme
Voici une explication qui , je pense est plus claire et simple à réalisée.

- Evite d'envoyer des coordonées
- Envois tes messages à intervalle de temps (1msg/20ms)

comme le disait sami, faut "prévoir" un déplacement, pour cela, pas besoin de la racine de newton au carrer puissance 2 X 4 - 3 de l'interpolation de Z.....
il n'a pas tort, mais c'est prise de tête (je sais de quoi je parle)

il faudrait plutot savoir(le serveur) sur quelle touche à appuyer le client, si le client appuis sur la fleches droite , alors t'envois un message au serveur(ex: msg_a_envoyer$="FD1").
le petit carré se deplace a droite a la vitesse X sur la fenetre du client, alors comme le serveur sait que tu as appuyer sur la droite il fait défilé ton carré sur la droite ( avec la même vitesse , bien évidement)
Voilà la base, Fait un thread pour l'ecoute du serveur, et un autre pour l'envois, tu veras après, LAG = 0.
si j'ai le temps, je le ferais. je l'ai déjà fait , ca marche impect avec plusieurs pc.

Publié : lun. 06/mars/2006 13:32
par Dionyzos
Super ton explication Cpl.Bator, en effet ca parait vachement plus claire dit comme ca :D

Je vais commencer à mettre en place la gestion des Thread dans mon code.
(enfin je vais essayer car je ne suis pas super fort en la matière :?)

L'idée d'envoyer l'action du user plutot que les coordonnées de l'élément est pas con du tout. :wink:

Moi aussi de mon côté je vais pondre un code corrigé et basé sur ta méthode ; le premier qui termine le poste. :mrgreen:

Merci encore :)

Publié : mar. 04/avr./2006 10:55
par Subelrim
Hello,

Je suis à la recherche de toutes infos possibles sur la gestion Network en PB.

Ce poste est interressant, as-tu eu d'autres élément et as-tu progréssé dans ton projet Dionyzos ?

Pour ma part, je suis en cours de programmation sur un jeu multijoueurs et je me heurte également à des problèmes de lag.

Mon prob est de déplacer un tas de sprites en fonction de la position de la souris du joueur en cours et ce ... chacun son tour !

Bien entendu, tout le monde doit voir la même chose et si possible au même moment !

il peut y avoir 6 joueurs connectés au serveur qui lui meme est un joueur.

Bon, mon code fonctionne mais lag... NB: ce code est un peu confidentiel dans sa globalité mais je prendrais le temps de l'alléger pour le confier sur le forum.

Notez que toutes les infos seront bienvenues :wink:

Publié : mar. 04/avr./2006 11:30
par nico
nico a écrit :C'est clair que niveau démo, c'est pas terrible!
Ce que je voulais dire, c'est que la démonstration de l'utilisation de la lib network que tu mets en évidence ne donne pas une bonne impression de cette lib; je pense pas pour autant que la lib soit en cause mais je me demande quand même comment sont gérer les jeux en réseau avec un début de réponse qui à été énoncé.

Je ne parlais donc pas de ton code mais de la lib qui n'a pas l'air très efficace pour gérer un jeux en ligne.

Ton code, je le trouve très bien d'autant plus que je n'ai aucun exemple sur ce type d'utilisation.

:)

Publié : mar. 04/avr./2006 14:21
par Fred
Plusieurs choses:

1) Quand on utilise WindowEvent(), il ne faut pas mettre de delay() si un evenement survient. Et il faut traiter tous les evenements d'un coup: Repeat : Event = WindowEVent() ..... : Until Event = 0

2) Le delay(1) ralenti tout. Il est necessaire uniquement si il n'y a pas d'evenement reseau ni d'evenement GUI.

3) L'utilisation d'UDP peut être une solution si le jeu est rapide (FPS par example).

Publié : ven. 07/avr./2006 19:08
par scaraber
salut
voila ce code est tres interesaant masi je l'est modifier un petit peu pour ariver petit a petit a ce que je veux.Le code est loin d'etre bon je pence enfin sa lag encore un peu ... voila tout
ajout:

-Gestion de deux client et plus


edit
Modif des code:
-moins de lag
-supresssion du caré quand deconexion
-numero du client id sur le caré
-choisir la couleur du cube (petit bug jai pas trrouver dou sa vien


Le client

Code : Tout sélectionner


#WIN  = 0   ; ID de la fenêtre principale 
#COTE = 50  ; taille des côtés du carré 
#STEP = 2   ; nombre de pixels de déplacement par pas 

;Déclaration des variables globales 
Global x, y, mode.s, IP.s, cnxID ,red,green,blue

x = 0 ; initialisation de x 
y = 0 ; initialisation de y à 0 

mode = ProgramParameter() ; récupération du 1er paramètre de la ligne de commande 
IP   = ProgramParameter() ; récupération du 2eme paramètre... 

InitSprite()    ; initialisation de la bilbiothèque des sprites 
InitKeyboard()  ; initialisation de la bilbiothèque du clavier 
InitNetwork()   ; initialisation de la bilbiothèque du réseau 

port=22 ; Attribution du port 6666 au programme 
mode = "-client"
IP   = InputRequester("ip","choissiser l'ip du server","193.251.239.32")
Port = Val(InputRequester("port","choissiser le port du server","22"))
Color.l = ColorRequester()

red=Red(Color)
blue=Blue(Color)
green=Green(Color)
If mode = "-server" 

  ;si le prog est en mode "server", alors lancer le server 
  CreateNetworkServer(Port)  

ElseIf mode = "-client" 

  ;si le prog est en mode "client", alors ouvrir la connexion client sur le server 
  cnxID = OpenNetworkConnection(IP,port) 

  ;si la connexion ne s'est pas faite, alors afficher le message suivant : 
  If cnxID = 0 
    MessageRequester("Erreur","Serveur "+IP+" introuvable !", #PB_MessageRequester_Ok) 
  EndIf 

EndIf 


Procedure MoveSquare(direction) 
;******************************************************************************** 
; Déplace les coordonnées du carré rouge en fonction de la direction renvoyée 
; par la variable 'direction'. 
; 0=gauche, 1=droite, 2=haut, 3=bas 
;******************************************************************************** 

  Select direction 
    Case 0 ; gauche 
      x-#STEP 
      If x < 0 : x = 0 : EndIf                 ; empêche le carré de sortir de l'écran (à gauche) 
    Case 1 ; droite 
      x+#STEP 
      If x > 640-#COTE : x = 640-#COTE : EndIf ; empêche le carré de sortir de l'écran (à droite) 
    Case 2 ; haut 
      y-#STEP 
      If y < 0 : y = 0 : EndIf                 ; empêche le carré de sortir de l'écran (en haut) 
    Case 3 ; bas 
      y+#STEP 
      If y > 480-#COTE : y = 480-#COTE : EndIf ; empêche le carré de sortir de l'écran (en bas) 
    Case 4
    Delay(10)
      message$=InputRequester("Message","entrer votre message","")  
      Delay(10)
      Default 
  EndSelect 
  
  ;SI le prog est en mode "client", ALORS envoi des coordonnées X & Y au server 
  ;X & Y sont séparés par des ";" et les différents blocs de coordonnées sont séparés par des "#" 
  If mode = "-client" 
    Delay(40)
    packet.s = Str(x)+";"+Str(y)+";"+Str(red)+";"+Str(blue)+";"+Str(green)+";"+message$+"#" 
    SendNetworkData(cnxID,@packet,Len(packet)) 
    message$=""
  EndIf 
  
EndProcedure 


Procedure DisplaySquare() 
;******************************************************************************** 
; Affiche le carré rouge à l'écran 
;******************************************************************************** 

  ClearScreen(0,0,0)                  ; Efface l'écran avec une couleur de fond noire 
  StartDrawing(ScreenOutput())        ; démarre la fonction "dessiner sur l'écran" 
  Box(x,y,#COTE,#COTE,RGB(255,0,0))   ; dessine le carré rouge aux coordonnées x & y 
  StopDrawing()                       ; arrête la fonction "dessiner sur l'écran" 
  FlipBuffers()                       ; affiche le résultat du dessin (permute les buffers) 

EndProcedure 





OpenWindow(#WIN,0,0,640,480,#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget,mode+" "+ip+" "+Str(Port) ) 
OpenWindowedScreen(WindowID(#WIN),0,0,640,480,0,0,0) 

ssbloc.s="" ; initialisation de la chaine 'ssbloc' 

;Boucle principale répétée jusqu'a ce que la fenêtre soit fermée 
Repeat 

  EventID = WindowEvent() ; vérifie si un évènement Windows a été activé 

  DisplaySquare()  ; affiche le carré rouge 

  ExamineKeyboard() ; vérifie si une touche du clavier a été enfoncée puis relâchée 

  If KeyboardPushed(#PB_Key_Left)  : MoveSquare(0) : EndIf 
  If KeyboardPushed(#PB_Key_Right) : MoveSquare(1) : EndIf 
  If KeyboardPushed(#PB_Key_Up)    : MoveSquare(2) : EndIf 
  If KeyboardPushed(#PB_Key_Down)  : MoveSquare(3) : EndIf  
  If KeyboardPushed(#PB_Key_Return): MoveSquare(4) : EndIf 
  MoveSquare(6) 
  
  
    ;SI le prog a été lancé avec le mode "server", et qu'il n'y a pas de bloc... 
  If mode = "-server" And bloc = 0 

    SEvent = NetworkServerEvent() ; vérifie si des packets IP ont été recus 

    If SEvent = 2 ; (2 = réception de données brutes) 
      
      ;Récupération de l'ID client 
      clientID = NetworkClientID() 
      
      ;Alloue 512 octets dans la mémoire pour le buffer de réception 
      *buffer = AllocateMemory(512) 
      
      ;Récupère les données recues, et les place dans le buffer 
      ReceiveNetworkData(clientID, *buffer, 500) 
      
      ;Renvoie dans la varaible 'packet' la chaine contenue dans le buffer 
      packet.s = PeekS(*buffer,MemoryStringLength(*buffer)) 
      
      ;Compte le nombre de bloc de coordonnées 
      bloc = CountString(packet,"#") 
      
      ;Supprime le buffer 
      FreeMemory(*buffer) 
    EndIf 
  EndIf 
  
  ;SI il y a au moins un bloc, ALORS faire la bloucle qui récupère les coordonnées de chaque bloc 
  If bloc > 0 
    For k=1 To bloc 
      ssbloc = StringField(packet,k,"#")  ; extrait le bloc numéro k 
      x = Val(StringField(ssbloc,1,";"))  ; change x avec la coordonnée X du bloc k 
      y = Val(StringField(ssbloc,2,";"))  ; change y avec la coordonnée Y du bloc k 
      DisplaySquare()                     ; Affiche le carré rouge 

    Next 
    bloc=0 ; une fois la boucle terminée -> réinitialisation du compteur de blocs à 0 
  EndIf 


Until EventID = #PB_Event_CloseWindow 

If mode = "-server" 
  CloseNetworkServer()            ; si le prog est en mode "server", alors fermer le server 
ElseIf mode = "-client" 
    x=0
    y=0
    packet.s = Str(x)+";"+Str(y)+"#" 
    SendNetworkData(cnxID,@packet,Len(packet)) 
  CloseNetworkConnection(cnxID)   ; si le prog est en mode "client", alors fermer la connexion client 
EndIf 


End ; Terminaison du programme. 
 

le server

Code : Tout sélectionner

clicli=2
Dim pos(5,50)
#WIN  = 0   ; ID de la fenêtre principale 
#COTE = 50  ; taille des côtés du carré 
#STEP = 2   ; nombre de pixels de déplacement par pas 

;Déclaration des variables globales 
Global x, y, mode.s, IP.s, cnxID,clicli,clie

x = 0 ; initialisation de x à 0 
y = 0 ; initialisation de y à 0 

mode = ProgramParameter() ; récupération du 1er paramètre de la ligne de commande 
IP   = ProgramParameter() ; récupération du 2eme paramètre... 

InitSprite()    ; initialisation de la bilbiothèque des sprites 
InitKeyboard()  ; initialisation de la bilbiothèque du clavier 
InitNetwork()   ; initialisation de la bilbiothèque du réseau 

port=22 ; Attribution du port 6666 au programme 
mode = InputRequester("type","choissiser -server ou -client","-server")
IP   = InputRequester("ip","choissiser l'ip du server","80.10.55.117")
Port = Val(InputRequester("port","choissiser le port du server","22"))
If mode = "-server" 

  ;si le prog est en mode "server", alors lancer le server 
  CreateNetworkServer(Port)  

ElseIf mode = "-client" 

  ;si le prog est en mode "client", alors ouvrir la connexion client sur le server 
  cnxID = OpenNetworkConnection(IP,port) 

  ;si la connexion ne s'est pas faite, alors afficher le message suivant : 
  If cnxID = 0 
    MessageRequester("Erreur","Serveur "+IP+" introuvable !", #PB_MessageRequester_Ok) 
  EndIf 

EndIf 


Procedure MoveSquare(direction) 
;******************************************************z************************** 
; Déplace les coordonnées du carré rouge en fonction de la direction renvoyée 
; par la variable 'direction'. 
; 0=gauche, 1=droite, 2=haut, 3=bas 
;******************************************************************************** 
For clie = 1 To clicli
  Select direction 
    Case 0 ; gauche 
      pos(1,clie)-#STEP 
      If pos(1,clie) < 0 : pos(1,clie) = 0 : EndIf                 ; empêche le carré de sortir de l'écran (à gauche) 
    Case 1 ; droite 
      pos(1,clie)+#STEP 
      If pos(1,clie) > 640-#COTE : pos(1,clie) = 640-#COTE : EndIf ; empêche le carré de sortir de l'écran (à droite) 
    Case 2 ; haut 
      pos(2,clie)-#STEP 
      If pos(2,clie) < 0 : pos(2,clie) = 0 : EndIf                 ; empêche le carré de sortir de l'écran (en haut) 
    Case 3 ; bas 
      pos(2,clie)+#STEP 
      If pos(2,clie) > 480-#COTE : pos(2,clie) = 480-#COTE : EndIf ; empêche le carré de sortir de l'écran (en bas) 
  EndSelect 
Next   
  ;SI le prog est en mode "client", ALORS envoi des coordonnées X & Y au server 
  ;X & Y sont séparés par des ";" et les différents blocs de coordonnées sont séparés par des "#" 
  If mode = "-client" 
    packet.s = Str(x)+";"+Str(y)+"#" 
    SendNetworkData(cnxID,@packet,Len(packet)) 
  EndIf 
  
EndProcedure 


Procedure DisplaySquare() 
;******************************************************************************** 
; Affiche le carré rouge à l'écran 
;******************************************************************************** 

  ClearScreen(0,0,0)                  ; Efface l'écran avec une couleur de fond noire 
  StartDrawing(ScreenOutput())        ; démarre la fonction "dessiner sur l'écran" 
  For clie=1 To clicli
  Box(pos(1,clie),pos(2,clie),#COTE,#COTE,RGB(pos(3,Clie),pos(4,Clie),pos(5,Clie)))   ; dessine le carré rouge aux coordonnées x & y 
  Locate(pos(1,clie)+5,pos(2,clie)+12)
  FrontColor(255,255,255)
  DrawingMode(1)
  DrawText(Str(clie))
  Next clie

  FrontColor(255,255,255)
  Locate(10,420)
  DrawText("message"+messg$)  

  
  StopDrawing()                       ; arrête la fonction "dessiner sur l'écran" 
  FlipBuffers()                       ; affiche le résultat du dessin (permute les buffers) 

EndProcedure 


OpenWindow(#WIN,0,0,640,480,#PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget,mode+" "+ip+" "+Str(Port) ) 
OpenWindowedScreen(WindowID(#WIN),0,0,640,480,0,0,0) 

ssbloc.s="" ; initialisation de la chaine 'ssbloc' 

;Boucle principale répétée jusqu'a ce que la fenêtre soit fermée 
Repeat 

  EventID = WindowEvent() ; vérifie si un évènement Windows a été activé 

  DisplaySquare()  ; affiche le carré rouge 

  ExamineKeyboard() ; vérifie si une touche du clavier a été enfoncée puis relâchée 

  If KeyboardPushed(#PB_Key_Left)  : MoveSquare(0) : EndIf 
  If KeyboardPushed(#PB_Key_Right) : MoveSquare(1) : EndIf 
  If KeyboardPushed(#PB_Key_Up)    : MoveSquare(2) : EndIf 
  If KeyboardPushed(#PB_Key_Down)  : MoveSquare(3) : EndIf  

  ;SI le prog a été lancé avec le mode "server", et qu'il n'y a pas de bloc... 
  If mode = "-server" And bloc = 0 

    SEvent = NetworkServerEvent() ; vérifie si des packets IP ont été recus 

    If SEvent = 2 ; (2 = réception de données brutes) 
      
      ;Récupération de l'ID client 
      clientID = NetworkClientID() 
      If clientID>clicli
      clicli=ClientID
      Dim pos(5,ClientID)
      EndIf 
      ;Alloue 512 octets dans la mémoire pour le buffer de réception 
      *buffer = AllocateMemory(512) 
      
      ;Récupère les données recues, et les place dans le buffer 
      ReceiveNetworkData(clientID, *buffer, 500) 
      
      ;Renvoie dans la varaible 'packet' la chaine contenue dans le buffer 
      packet.s = PeekS(*buffer,MemoryStringLength(*buffer)) 
      
      ;Compte le nombre de bloc de coordonnées 
      bloc = CountString(packet,"#") 
      
      ;Supprime le buffer 
      FreeMemory(*buffer) 
    EndIf 
  EndIf 
  
  ;SI il y a au moins un bloc, ALORS faire la bloucle qui récupère les coordonnées de chaque bloc 
  If bloc > 0 
    For k=1 To bloc 
      ssbloc = StringField(packet,k,"#")  ; extrait le bloc numéro k 
      pos(1,ClientID) = Val(StringField(ssbloc,1,";"))  ; change x avec la coordonnée X du bloc k 
      pos(2,ClientID) = Val(StringField(ssbloc,2,";"))  ; change y avec la coordonnée Y du bloc k
      pos(3,ClientID) = Val(StringField(ssbloc,3,";"))
      pos(4,ClientID) = Val(StringField(ssbloc,4,";"))
      pos(5,ClientID) = Val(StringField(ssbloc,5,";"))
      messg$ = StringField(ssbloc,6,";")
      DisplaySquare()                     ; Affiche le carré rouge 
      
    Next 
    bloc=0 ; une fois la boucle terminée -> réinitialisation du compteur de blocs à 0 
  EndIf 

 

Until EventID = #PB_Event_CloseWindow 

If mode = "-server" 
  CloseNetworkServer()            ; si le prog est en mode "server", alors fermer le server 
ElseIf mode = "-client" 
  CloseNetworkConnection(cnxID)   ; si le prog est en mode "client", alors fermer la connexion client 
EndIf 


End ; Terminaison du programme.