Interface web / application

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Interface web / application

Message par Kwai chang caine »

Bonjour à tous

C'est encore KCC qui gagne une tringle a rideau !!!!

Je vais poser encore une question idiote. :oops:
Mais comme c'est encore un domaine que je n'ai pas exploré.....

Je voudrais savoir, si je peux me lancer "Assez simplement" dans une appli client qui contiendrait un WebBrowser interrogeant sur une autre machine une appli serveur
L'appli serveur enverrait la page a afficher, et surtout elle pourrait recevoir les commandes du client, selon si l'utilisateur du client clique sur un lien, ou appuie sur un bouton de la page.....

Parce que envoyer la page au client, ça je vois a peu pres comment faire, que le client l'affiche, ça devrait aussi aller, mais la partie obscure de la force, c'est comment le serveur peut il recevoir un ordre du client suite à un clic de lien ???? :roll:

Merci de m'eclaircir de vos lumieres
Bonne journée
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Salut KCC,

ce que tu expliques correspond à une appli WEB tout à fait classique. Il y a des applis gratuites qui font ça très bien (WAMP par exemple : Apache, MySQL, PHP pour Windows) + ton navigateur classique.

Je n'ai peut être pas bien compris ce que tu souhaites faire, mais le HTML standard semble répondre à tes besoins. Le client "commande" le serveur en lui envoyant des requêtes POST/GET... Le serveur y répond en envoyant une page complète (HTML classique), des bouts de code HTML (type AJAX), des flux (applets/servlets J2EE), ...
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

Merci de ta reponse rapide :D

Je voudrais creer ces deux applis, car la ou je bosse, on ne peut pas, ou difficilement installer des applis serveur comme apache, etc ...)

Donc j'avais pensé utiliser le FTP de pure, comme ça hors mis mon appli posée sur le PC serveur et qui ne necessite pas d'installation BDR et tout le toutim, je n'installe rien.

Juste a démarrer mon appli sur le PC serveur, et hop ça fait un style de serveur simplifié pouvant envoyer au client des pages HTML ou javascript :D
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

Je me pose une autre question :roll:
Si l'on a un PC avec une appli serveur qui tourne
Et que un client se connecte dessus.

Est ce qu'un autre client peut se connecter sur le PC serveur ou faut il attendre que le premier client se deconnecte ???
Avatar de l’utilisateur
Le psychopathe
Messages : 764
Inscription : jeu. 03/mars/2005 19:23

Message par Le psychopathe »

Kwai chang caine a écrit :Je me pose une autre question :roll:
Si l'on a un PC avec une appli serveur qui tourne
Et que un client se connecte dessus.

Est ce qu'un autre client peut se connecter sur le PC serveur ou faut il attendre que le premier client se déconnecte ???
Bien sur qu'un autre client peut se connecter dessus.
Jettes un coup d œil à mon poste en dessous : network chat
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Plusieurs clients peuvent se connecter simultanément. Pour ça, tu as la fonction EventClient() qui permet d'identifier quel client à envoyer des données au serveur.

Concernant ton post précédent, ce que je te conseille c'est de réutiliser la base du serveur fourni en exemple avec PB. En gros tu créés ton propre serveur web (assez light pour ne pas à avoir à installer un gros système, mais assez puissant pour répondre à tes besoins).

Je crois que j'avais fait un serveur de ce genre, je vais essayer de retrouver le post ;)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

Merci à vous deux pour vos reponses.

@Le psychopathe
Je vais jeter un oeil a ton CHAT

@Cls
C'est sympa, ça pourrais me faire un autre exemple pour bien comprendre

Est ce qu'a votre avis une machine peut etre serveur Et client;
En installant un serveur et un client dans le meme programme, et ce programme dans chacune des machines :roll:
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Oui c'est le principe des réseaux Peer 2 Peer. J'en ai fait un vite fait, je poste le code de suite ('fin quand je l'aurai retrouvé :oops: ).
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

('fin quand je l'aurai retrouvé ).
:lol:

Ouuuaaahh !! merci CLS
C'est vrai il a raison le PSY :wink:
Y'a pas foule ceux qui connaissent le reseau.

T'es une perle toi 8)

Le reseau c'est l'avenir, et moi comme j'y connais rien en reseau, j'ai pas d'avenir :cry:

Merci de ta precieuse aide
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Ok j'ai retrouvé le code.

Je suis désolé, j'ai dû prendre une ancienne version d'un projet et le code n'est pas du tout fini. Je mettrai trop de temps à modifier la version complète. J'espère que ça pourra te donner des idées.

Code : Tout sélectionner

; -------------------------------------------
;- Module Peer2Peer
; -------------------------------------------


; Interfaces


Enumeration
  #Window_9
  #Frame3D_20
  #Frame3D_21
  #Frame3D_23
  #Tree_0
  #Text_151
  #String_98
  #Text_152
  #Button_47
  #Panel_2
  #Panel_3
  #String_100
  #Button_48
  #Listview_1
  #String_101
  #Panel_4
  #Text_154
  #username
  #Text_155
  #String_104
  #Listview_2
  #ListIcon_9
  #Text_156
  #Text_157
  #Text_159
  #String_105
  #String_106
  #String_107
  #Text_161
  #Text_162
  #String_109
  #String_111
EndEnumeration

Procedure Open_Window_9()
  If OpenWindow(#Window_9  , 221, 181, 992, 671, "Réseau Peer 2 Peer",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
    If CreateGadgetList(WindowID(#Window_9  ))
      Frame3DGadget(#Frame3D_20, 5, 5, 195, 330, "Clients connectés")
      Frame3DGadget(#Frame3D_21, 5, 465, 195, 200, "Etat du réseau")
      Frame3DGadget(#Frame3D_23, 5, 345, 195, 110, "Amorçage")
      TreeGadget(#Tree_0, 15, 25, 175, 300)
      TextGadget(#Text_151, 15, 370, 25, 15, "IP")
      StringGadget(#String_98, 50, 390, 45, 20, "")
      TextGadget(#Text_152, 15, 395, 25, 15, "Port")
      ButtonGadget(#Button_47, 55, 425, 90, 20, "Connecter")
      StringGadget(#String_100, 210, 645, 770, 20, "")
      ButtonGadget(#Button_48, 15, 490, 170, 20, "Démarrer le serveur")
      ListViewGadget(#Listview_1, 15, 515, 170, 140)
      StringGadget(#String_101, 50, 365, 135, 20, "")
      
      ;- Panel15
      PanelGadget(#Panel_2, 210, 10, 775, 410)

      AddGadgetItem(#Panel_2, -1, "Options")
      
      ;- Panel22
      PanelGadget(#Panel_4, 8, 8, 755, 370)
      AddGadgetItem(#Panel_4, -1, "Général")
      TextGadget(#Text_154, 13, 13, 95, 15, "Nom d'utilisateur :")
      StringGadget(#username, 113, 8, 130, 20, "TT Défaut !")
      AddGadgetItem(#Panel_4, -1, "Serveur")
      TextGadget(#Text_155, 18, 13, 75, 20, "Port d'écoute :")
      StringGadget(#String_104, 108, 8, 55, 20, "1539")
      CloseGadgetList()
      AddGadgetItem(#Panel_2, -1, "Logs")
      ListViewGadget(#Listview_2, 8, 8, 755, 370)
      CloseGadgetList()
      
      ;- Panel20
      PanelGadget(#Panel_3, 210, 430, 775, 210)
      AddGadgetItem(#Panel_3, -1, "Salle commune")
      CloseGadgetList()
      
    EndIf
  EndIf
EndProcedure

Structure CLIENT
  id.l
  ip.l
  port.l
  nom.s
  last_action.l
  last_action_date.l
  ping_sent.b
EndStructure

Global NewList Client.CLIENT()


Structure THREADPARAMETERS
  client_ip.l
  client_port.l
  requete_type.b
  connect_ip.s
  param1.s
  param2.l
  
EndStructure

Global Serveur.l = 0 
Global Network.l = 0

#Port = 1539
Global Port.l = #Port

Global Network_Password.s = "pass"


#TimeOutPing = 10 ; Durée en secondes après laquelle un client est ping-é (on lui envoi un ping, il renvoi un pong)
#TimeOut = 20 ; Durée en secondes après laquelle un client est considéré inactif et sorti de la liste des clients (il n'a pas répondu à un ping)


; Type de Network Packet
Enumeration 1
  #Connect
  #Disconnect
  #Clients
  #Message
  #File
  #Ping
  #Pong
  #Name
  #Network_Password
  #None
  
  #Commun_Attaque
  #Add_Village
EndEnumeration

;-
; -------------------------------------------------------------------------------------------------
;- === procedure RESEAU & SYSTEM =====
; -------------------------------------------------------------------------------------------------

;-------------------  Semaphore Functions  ------------------------
Macro Sem_Create(Init, Max)
  CreateSemaphore_(#Null, Init, Max, #Null)
EndMacro

Macro Sem_Acquire(Sem)
  WaitForSingleObject_(Sem, #INFINITE)
EndMacro

Macro Sem_ReleaseSeveral(Sem, nb)
  ReleaseSemaphore_(Sem, nb, #Null)
EndMacro
Macro Sem_Release(Sem)
  ReleaseSemaphore_(Sem, 1, #Null)
EndMacro
;----------------  End of Semaphore Functions  --------------------- 

Global AccessThreadParameters = Sem_Create(1, 1) ; Créer une sémaphore



Procedure GetNetworkPacketType(*buffer)  
  ProcedureReturn PeekL(*buffer)
EndProcedure

; Identifiant unique d'un client
; Ce système garanti l'unicité de numéro donné aux clients.
Global UNIQUE_CLIENT_IDENTIFIANT.l = 1

Procedure.l GetUCI()
  ret.l = UNIQUE_CLIENT_IDENTIFIANT
  UNIQUE_CLIENT_IDENTIFIANT + 1 
  ProcedureReturn ret
EndProcedure


; --------------------------------------------------------------------
;- Gestion du serveur
; --------------------------------------------------------------------

; Ajoute un client dans la liste des clients connus
Procedure AddClient(clientID.l, clientIP.l, clientPort.l, nom.s, date.l, last_action.l = #Connect)
  
  ; Vérifie qu'il n'existe pas
  client_existe.b = #False 
  ForEach Client()
  
    If Client()\ip = clientIP And Client()\port = clientPort
      client_existe = #True
      Break
    EndIf
  Next
  
  If client_existe = #False
    AddElement(Client())
    Client()\id = GetUCI()
    Client()\ip = clientIP
    Client()\port = clientPort
    Client()\nom = nom
    Client()\last_action = last_action
    Client()\last_action_date = date  
  
  Else
    ; Le client existe déjà, on ne fait rien ;)
  EndIf
  
  
EndProcedure

; Modifie un client connu
Procedure ModifClient(clientID.l, clientIP.l, clientPort.l, nom.s, date.l, last_action.l)
  
  ; Vérifie qu'il n'existe pas
  client_existe.b = #False 
  ForEach Client()
  
    If Client()\ip = clientIP And Client()\port = clientPort
      client_existe = #True
      Break
    EndIf
  Next
  
  If client_existe = #True
    ; Modifie le nom 
   
    Client()\nom = nom
    Client()\last_action = last_action
    Client()\last_action_date = date  
  
  Else
    ; Le client existe déjà, on ne fait rien ;)
  EndIf
  
  
EndProcedure

; Suprime un client de la liste des clients connus
Procedure RemoveClient(clientIP.l, clientPort.l)
  
  client_existe.b = #False 
  ForEach Client()
  
    If Client()\ip = clientIP And Client()\port = clientPort
      client_existe = #True
      Break
    EndIf
  Next
  
  If client_existe
    ; Le client existe, la liste chainée le référence : on supprime !
    
    DeleteElement(Client())
    
  EndIf
  
  
EndProcedure

; Modifie la dernière action du client.
; Utile pour savoir qu'un client est toujours UP
Procedure ClientLastAction(clientID, clientIP, clientPort, last_action, date)
  client_existe.b = #False 
  ForEach Client()
  
    If Client()\ip = clientIP And Client()\port = clientPort
      client_existe = #True
      Break
    EndIf
  Next
  
  If client_existe
    Client()\last_action = last_action
    Client()\last_action_date = date
    Client()\ping_sent = 0 ; Autorise de nouveau le ping
  EndIf

EndProcedure

; Ajoute l'entête d'un packet de données
Procedure.l AddPacketHeader(*buffer, header.l)
  
  PokeL(*buffer, header)
  
  ProcedureReturn *buffer
EndProcedure

; Procédure permettant d'envoyer à un client, un packet déjà créé
Procedure.b SendPacket(hote.s, port.l, packet.l, length.l)
  conn = OpenNetworkConnection(hote, port, #PB_Network_UDP)
  ret.b = #False
  
  If conn
  
    SendNetworkData(conn, packet, length)
    CloseNetworkConnection(conn)
    
    ret = #True
    
  EndIf
    
  ProcedureReturn ret
EndProcedure

; Procédure permettant de créer une requête.
; Elle doit être lancée dans un thread et synchronisée avec une sémaphore
Procedure CreateRequete(Param.l)
  
  Global AccessThreadParameters
  Global Port
  
  *LocalParameters.THREADPARAMETERS = Param
  
  
  
  ; TRaitement : création de la requête en fonction des parametres 
  
  Debug "THREAD Client : "
  Debug IPString(*LocalParameters\client_ip) + " : " + Str(*LocalParameters\client_port)
  
  ; Libère la variable pour l"affectation
  ;UnlockMutex(AccessThreadParameters)
  
  ; Dans le cas d'une requete de type CLIENTS on libère la mémoire plus tard
  If *LocalParameters\requete_type <> #Clients
    Sem_Release(AccessThreadParameters)
    
  EndIf
  
  ; En fonction du type de requête, fais des actions différentes
  
  ; Partie commune, l'envoi du packet est factorisé
  length.l = 0
  *packet = 0
  
  
  ; Création du packet
  Select *LocalParameters\requete_type
    Case #Ping
      
      ; Envoi un PING
      *ping_packet = AllocateMemory(64)
      *ping_packet = AddPacketHeader(*ping_packet, #Ping)
      
      PokeL(*ping_packet + 4, Port)
    
      *packet = *ping_packet
      length = 8
    
    
    Case #Pong
    
      ; Envoi un PONG
      *pong_packet = AllocateMemory(64)
      *pong_packet = AddPacketHeader(*pong_packet, #Pong)
      
      PokeL(*pong_packet + 4, Port)
    
      *packet = *pong_packet
      length = 8
    
    
    Case #Connect
      
      ; Création du packet de données
      *connect_packet = AllocateMemory(9128)
      
      ; #Connect
      ; Format : CONNECT|REMOTE_SERVER_PORT(long)|NAME(str)|PASSWORD(str)
      
      *connect_packet = AddPacketHeader(*connect_packet, #Connect)
      PokeL(*connect_packet + 4, Port)
      
      nom.s = *LocalParameters\param1
      
      
      PokeL(*connect_packet + 8, Len(nom)) 
      
      PokeS(*connect_packet + 12, nom, Len(nom))

      *packet = *connect_packet
      length = 12 + Len(nom)    
    
    
    Case #Clients
      
      ; #Clients
      ; Format CLIENTS|REMOTE_SERVER_PORT(long)|NB_CLIENTS(long)|IP(long)|PORT(long)|NAME(str)|[...]
      
      ; Copie en local la liste des clients é envoyer et libère la mémoire.
      NewList Clt.CLIENT()
      *Clt = @*LocalParameters\param2
      
      Sem_Release(AccessThreadParameters)
    
      ; Création du packet de données
      *client_packet = AllocateMemory(9128)
      
      *client_packet = AddPacketHeader(*client_packet, #Clients)
      PokeL(*client_packet + 4, Port)
      
      ; Nombre de clients
      PokeL(*client_packet + 8, CountList(Clt()))
      
      FirstElement(Clt())
      nb_clt.l = 0
      delta_clt.l = 0
      While nb_clt < CountList(Clt())
      
        PokeL(*client_packet + 12 + delta_clt , Clt()\ip)
        PokeL(*client_packet + 16 + delta_clt , Clt()\port)
        
        PokeL(*client_packet + 20 + delta_clt , Len(Clt()\nom))
        
        PokeS(*client_packet + 24 + delta_clt , Clt()\nom, Len(Clt()\nom))
        
        
        delta_clt + 13
        delta_clt + Len(Clt()\nom)
      
        nb_clt + 1
        NextElement(Clt())
      Wend
      
      
      ; Informations sur le packet
      *packet = *client_packet
      length = 12 + delta_clt
      
    
    Case #Name
      
      
      ; Création du packet de données
      *name_packet = AllocateMemory(512)
      
      ; #Name
      ; Format : NAME|REMOTE_SERVER_PORT(long)|NOM(str)
      
      *name_packet = AddPacketHeader(*name_packet, #Name)
      PokeL(*name_packet + 4, Port)
      
      nom.s = *LocalParameters\param1
      
      
      PokeL(*name_packet + 8, Len(nom)) 
      
      PokeS(*name_packet + 12, nom, Len(nom))
      
      
      ; Informations sur le packet
      *packet = *name_packet
      length = 12 + Len(nom) 
     
    
  EndSelect
  
  
  ; Envoi du packet
  If *LocalParameters\client_ip = 0 And *LocalParameters\connect_ip <> ""
    
    
    conn = OpenNetworkConnection(*LocalParameters\connect_ip, *LocalParameters\client_port, #PB_Network_UDP)
  
    If conn
      SendNetworkData(conn, *packet, length)
      CloseNetworkConnection(conn)
      Debug "Packet envoyé"
            
    EndIf

  
  Else
    
    conn = OpenNetworkConnection(IPString(*LocalParameters\client_ip), *LocalParameters\client_port, #PB_Network_UDP)
  
    If conn
      SendNetworkData(conn, *packet, length)
      CloseNetworkConnection(conn)
      Debug "Packet envoyé"
            
    EndIf
    
    
  EndIf
  
  
EndProcedure

; Ecrit des données dans le log
Procedure Logs(msg.s)
  
  imsg.s = FormatDate("%dd/%mm/%yy - %hh:%ii:%ss", Date()) + " " + msg
  AddGadgetItem(#Listview_2, -1, imsg)
EndProcedure


; -------------------------------------------------------------------------------------------------
;- ===== Procedure INTERFACE =====
; -------------------------------------------------------------------------------------------------

Procedure majListBoxClient()

  ClearGadgetItemList(#Tree_0)
  
  
  ForEach Client()

    nom_affiche.s = Client()\nom
    
    ; Si le client est en cours de ping mais ne répond pas...
    If Date() - Client()\last_action_date > #TimeOutPing And Client()\ping_sent = 1
    
      nom_affiche + " [Inactif]"
      
    EndIf
    
    AddGadgetItem(#Tree_0, -1, nom_affiche, 0, 0)
    
  Next

EndProcedure


Procedure majEtatReseau()
  
  ClearGadgetItemList(#Listview_1)
  
  ; Etat serveur
  msg.s = "Etat du serveur : "
  If Serveur : msg + "Activé" : Else : msg + "Désactivé" : EndIf
  
  AddGadgetItem(#Listview_1, -1, msg)
  
  If Serveur
    
    msg = "Port : " + Str(Port)
    AddGadgetItem(#Listview_1, -1, msg)
    
  EndIf
  
  ; Etat reseau
  AddGadgetItem(#Listview_1, -1, "")
  
  msg = "Réseau : "
  If Network : msg + "Connecté" : Else : msg + "Déconnecté" : EndIf
  AddGadgetItem(#Listview_1, -1, msg)
  
  msg = "Clients connus : " + Str(CountList(Client()))
  AddGadgetItem(#Listview_1, -1, msg)


  ; Met à jour ici la list box contenant les clients
  
  majListBoxClient()
  

EndProcedure




;- ===== Debut du programme =====
; ----------------------------------------------------------------------------

InitNetwork()

;Serveur = CreateNetworkServer(#PB_Any, #Port, #PB_Network_UDP)


; Ouverture de l'interface principale
Open_Window_9()

majEtatReseau()

If Serveur
  SetGadgetText(#Button_48, "Couper le serveur")
Else
  SetGadgetText(#Button_48, "Démarrer le serveur")
EndIf


Repeat


;- Gestion des évènements liés à la fenêtre
; ----------------------------------------------------------------------------
  EventID = WaitWindowEvent(10)
  
  
  Select EventID
    Case #PB_Event_CloseWindow
      End
      
    Case #PB_Event_Gadget
      
      
      Select EventGadget()
        
        
        Case #Button_47 ;- Connecter au réseau
          
          
          
          
          ; ----------------------
          ; Active d'abord le serveur avant de tenter une connexion
          ; -----------------------
          If Serveur = 0
            sPort.l = Val(GetGadgetText(#String_104))
            Serveur = CreateNetworkServer(#PB_Any, sPort, #PB_Network_UDP)
          
            If Serveur
              Port = sPort
            EndIf
          
          Else
            CloseNetworkServer(Serveur)
          EndIf
          
          majEtatReseau()

          If Serveur
            SetGadgetText(#Button_48, "Couper le serveur")
          Else
            SetGadgetText(#Button_48, "Démarrer le serveur")
          EndIf
          
          
          connect_ip.s = GetGadgetText(#String_101)
          connect_port.l = Val(GetGadgetText(#String_98))
          
          username.s = GetGadgetText(#username)
          
          
          If connect_ip And connect_port
          
            ; Envoi des données
            ; Sémaphore pour vérrouiller l'accès aux données
            Sem_Acquire(AccessThreadParameters)
        
            ThreadParameters.THREADPARAMETERS
            ThreadParameters\connect_ip = connect_ip
            ThreadParameters\client_port = connect_port
            ThreadParameters\requete_type = #Connect
            ThreadParameters\param1 = username
            
            ; Création du thread
            CreateThread(@CreateRequete(), @ThreadParameters)
            
            Network = 1
          
          Else
            
            MessageRequester("Connexion au serveur...", "Connexion au serveur impossible, il manque des données. Veuillez renseigner [IP | HOTE] : PORT", #MB_ICONEXCLAMATION)
          
          EndIf
                   
        
        Case #Button_48 ;- Activer le serveur
          
          If Serveur = 0
            sPort.l = Val(GetGadgetText(#String_104))
            Serveur = CreateNetworkServer(#PB_Any, sPort, #PB_Network_UDP)
          
            If Serveur
              Port = sPort
            EndIf
          
          Else
            CloseNetworkServer(Serveur)
            Serveur = 0
          EndIf
          
          majEtatReseau()

          If Serveur
            SetGadgetText(#Button_48, "Couper le serveur")
          Else
            SetGadgetText(#Button_48, "Démarrer le serveur")
          EndIf
          
          
      EndSelect
      
      

      
      
  EndSelect




;- Gestion des évènements liés au réseau
; ----------------------------------------------------------------------------

; Uniquement si le serveur est connecté et disponible
  If Serveur
  ;Debug "Server lancé sur le port " + Str(#Port)

    Delay(10)
    Event.l = NetworkServerEvent()
    
    Select Event
      
      Case 0
      
      
      Case #PB_NetworkEvent_Connect  ; : Un nouveau client s'est connecté au serveur.
        ; Pas d'évenement dans ce cas la.
        ; La connexion est acceptée mais on ne fait rien, on attend de voir ce que ce client veut !
        Debug "Client connect"
      
      Case #PB_NetworkEvent_Data      ;: Des données ont été reçues (à lire avec ReceiveNetworkData()) 
        
        ; On retrouve l'envoyeur
        clientID.l = EventClient()
        clientIP.l = GetClientIP(clientID)
        clientPort.l = GetClientPort(clientID)
        
        
        
        ; on lit les données
        #Buffer_size = 65536
        *buffer = AllocateMemory(#Buffer_size)
        octets_lus.l = ReceiveNetworkData(clientID, *buffer, #Buffer_size) 
        
        If octets_lus => #Buffer_size
          ; ***********************************************
          ; Mémoire tampon insuffisante !!! 
          ; Veuillez augmenter la taille de cette mémoire
          ; ***********************************************
          
        EndIf
        
        ;- ### TYPE PACKET 
        ; Type du message
        ; Effectue l'action qui va bien en fonction de l'entête du message
        Select GetNetworkPacketType(*buffer)
          ;- #Connect
          Case #Connect
            
            ; Format : CONNECT|REMOTE_SERVER_PORT(long)|NAME(str)|PASSWORD(str)
            
            ; Port du serveur du client
            dataPacketPort.l = PeekL(*buffer + 4) ; 4 = sizeOf(Long)
            
            ; Lit le nombre d'octet à lire
            octet_a_lire = PeekL(*buffer + 8)
            nom.s = PeekS(*buffer + 12, octet_a_lire)
            
            ; Lit le mot de passe
            octet_a_lire2 = PeekL(*buffer + 12 + octet_a_lire)
            password.s = PeekS(*buffer + 16 + octet_a_lire, octet_a_lire2)
            
            
            ; **** RESEAU SECURISE ***
            ;If Network_Password = password
            
              ; Ajoute le client à notre liste (s'il n'existe pas déjà)
              AddClient(clientID, clientIP, dataPacketPort, nom, Date())
            
            ;EndIf
            
            ; Met à jour CGC
            ClientLastAction(clientID, clientIP, dataPacketPort, #Connect, Date())
            
            majEtatReseau()
            
            ; Ecriture dans le log
            Logs("[in] CONNECT : " + IPString(clientIP) + ":" + Str(dataPacketPort) + ", user:" + nom)
            
            
            ; Renvoi au nouveau client la liste des clients connus
            ; -----------------------------------------------------
            
            
            
            
            clt_list = AllocateMemory(CountList(Client()) * SizeOf(CLIENT) + 8)            
            
            FirstElement(Client())
            CopyMemory(@Client(), @clt_list, CountList(Client()) * SizeOf(CLIENT))
            
            ; CTL_LIST contient désormais tous les clients connus
            
            
            ; Sémaphore pour vérrouiller l'accès aux données
            Sem_Acquire(AccessThreadParameters)
        
            ThreadParameters.THREADPARAMETERS
            ThreadParameters\client_ip = clientIP
            ThreadParameters\client_port = dataPacketPort
            ThreadParameters\requete_type = #Clients
            ThreadParameters\param2 = @clt_list; pointeur sur la liste des clients

            
            ; Création du thread
            CreateThread(@CreateRequete(), @ThreadParameters)
            
            
            ; Envoi au client nouvellement connecté le pseudo
            ; Sémaphore pour vérrouiller l'accès aux données
            Sem_Acquire(AccessThreadParameters)
        
            ThreadParameters.THREADPARAMETERS
            ThreadParameters\client_ip = clientIP
            ThreadParameters\client_port = dataPacketPort
            ThreadParameters\requete_type = #Name
            ThreadParameters\param1 = GetGadgetText(#username) ; le pseudo qui sera affiché chez le client 

            
            ; Création du thread
            CreateThread(@CreateRequete(), @ThreadParameters)
            
            
          
          ;- #Disconnect
          Case #Disconnect
            
            ; Format : DISCONNECT|REMOTE_SERVER_PORT(long)
            
            ; Port du serveur du client
            dataPacketPort.l = PeekL(*buffer + 4) ; 4 = sizeOf(Long)
            
            RemoveClient(clientIP, dataPacketPort)
            
            majEtatReseau()
            
            
            ; Ecriture dans le log
            Logs("[in] DISCONNECT : " + IPString(clientIP) + ":" + Str(dataPacketPort))
            
          ;- #Clients
          Case #Clients
            Debug "Clients"
            ; Format CLIENTS|NB_CLIENTS(long)|IP(long)|PORT(long)|NAME(str)|[...]
            
            ; Port du serveur du client
            dataPacketPort.l = PeekL(*buffer + 4) ; 4 = sizeOf(Long)
            
            ; Récupère la liste de tous les clients connus par un noeud du réseau            
            nb_clients.l = PeekL(*buffer + 8)
            
            idx.l = 0
            delta_nom.l = 0
            While idx < nb_clients
              
              ip.l = PeekL(*buffer + 12 + delta_nom)
              port_.l = PeekL(*buffer + 16 + delta_nom)
              
              octet_a_lire = PeekL(*buffer + 20 + delta_nom)
              
              nom.s = PeekS(*buffer + 24 + delta_nom, octet_a_lire)
              
              delta_nom + 13
              delta_nom + octet_a_lire
              
              idx + 1
              
              
              ; Ajoute le client à la liste s'il n'existe pas
              AddClient(0, ip, port_, nom, Date(), #None)
              
            Wend
            
            ; Ajoute le client qui envoi ces paquets
            AddClient(0, clientIP, dataPacketPort, "(default)", Date(), #None)
            
            
            ; Ecriture dans le log
            Logs("[in] CLIENTS : " + IPString(clientIP) + ":" + Str(dataPacketPort))
            
            majEtatReseau()
            

          ;- #Message
          Case #Message
            
            ; Format MESSAGE|REMOTE_SERVER_PORT(long)|DESTINATION(byte)|MESSAGE(str)
            
            ; Destination permet de savoir si c'est un message privé ou public ([0 | 1])
            
          ;- #File
          Case #File
          
          
          ;- #Ping
          Case #Ping
            
            ; Format PING|REMOTE_SERVER_PORT(long)
            
            ; Déclenche l'envoi d'un PONG vers l'envoyeur:)
            
            dataPacketPort.l = PeekL(*buffer + 4) ; 4 = sizeOf(Long)
            
            
            ; Sémaphore pour vérrouiller l'accès aux données
            Sem_Acquire(AccessThreadParameters)
        
            ThreadParameters.THREADPARAMETERS
            ThreadParameters\client_ip = clientIP
            ThreadParameters\client_port = dataPacketPort
            ThreadParameters\requete_type = #Pong

            
            ; Création du thread
            CreateThread(@CreateRequete(), @ThreadParameters)
            
            ; Met à jour CGC
            ClientLastAction(clientID, clientIP, dataPacketPort, #Ping, Date())
            
            ; Ecriture dans le log
            Logs("[in] PING : " + IPString(clientIP) + ":" + Str(dataPacketPort))
            
            ; Mise à jour de l'interface
            majEtatReseau()
            
          
          ;- #Pong
          Case #Pong
            
            ; Format PONG|REMOTE_SERVER_PORT(long)
            
            ; Réponse à un PING (ou pas ;)). Donne l'information comme quoi le client est tjs connnecté sur le réseau
            ; Port du serveur du client
            dataPacketPort.l = PeekL(*buffer + 4) ; 4 = sizeOf(Long)
            
            ; Modifie les données du client
            ClientLastAction(clientID, clientIP, dataPacketPort, #Pong, Date())
            
            ; Ecriture dans le log
            Logs("[in] PONG : " + IPString(clientIP) + ":" + Str(dataPacketPort))
            
            ; Mise à jour de l'interface
            majEtatReseau()
          
          ;- #Name
          Case #Name
            
            ; Format NAME|REMOTE_SERVER_PORT(long)|NOM(str)
            
            ; Modification du nom visible par tous
            
            ; Port du serveur du client
            dataPacketPort.l = PeekL(*buffer + 4) ; 4 = sizeOf(Long)
            
            ; Lit le nombre d'octet à lire
            octet_a_lire = PeekL(*buffer + 8)
            nom.s = PeekS(*buffer + 12, octet_a_lire)
            
            ; Modifie le client de notre liste (s'il n'existe pas déjà)
            ModifClient(clientID, clientIP, dataPacketPort, nom, Date(), #Name)
            
            ; Ecriture dans le log
            Logs("[in] NAME : " + IPString(clientIP) + ":" + Str(dataPacketPort))
          
          ; *********************** ADMIN ONLY *****************************************
          ;- #Network_Password
          Case #Network_Password
            
            
            ; Format NETWORK_PASSWORD|OLD_PASS(str)|NEW_PASS(str)
            
            ; Change le mot de passe pour entrer sur le réseau
            
          
        EndSelect
        
        
        
      
      Case #PB_NetworkEvent_File      ;: Un fichier a été reçu (à lire avec ReceiveNetworkFile()) 
      
      
      Case #PB_NetworkEvent_Disconnect
     
     
      
    EndSelect
 
    
    ;- CGC Client Garbage Collector
    ; Gestion des clients 
    ; Ping / Pong
    
    ForEach Client()
    
      ; Timeout de suppression du client
      If Date() - Client()\last_action_date > #TimeOut
        
        
        Debug "Suppression du client [cause : inactivité]"
        DeleteElement(Client()) ; Supprime le client et passe au suivant
      
        majEtatReseau()
        
        Continue
        
        
      EndIf
      
      
      
      ; Si le timeout d'envoi d'un ping est dépassé et que celui ci n'a pas déjà été envoyé
      If Date() - Client()\last_action_date > #TimeOutPing And Client()\ping_sent = 0
      
        ; Pour chaque client on va créer un thread pour l'envoi d'une requete      
        ; Créé une zone mémoire avec les infos à passer aux threads 
        ; et la vérrouille afin que le thread est le temps de lire
        ;LockMutex(AccessThreadParameters)
        Sem_Acquire(AccessThreadParameters)
        
        
        ThreadParameters.THREADPARAMETERS
        ThreadParameters\client_ip = Client()\ip
        ThreadParameters\client_port = Client()\port
        ThreadParameters\requete_type = #Ping
        
        ; Interdit le ping jusqu'à ce qu'une réponse soit recue
        Client()\ping_sent = 1
        
        ; Création du thread
        CreateThread(@CreateRequete(), @ThreadParameters)
        
        
        majEtatReseau()  
      
      EndIf
      
      
    Next
    
  EndIf ; Fin gestion du serveur

  

ForEver

End
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Je mets également le fichier que j'ai utilisé pour les tests correspondant au code ci - dessus :

Code : Tout sélectionner

; Test Peer2Peer
; 
; Fichier de test permettant d'envoyer des données au server et de tester ces réactions

Enumeration 1
  #Connect
  #Disconnect
  #Clients
  #Message
  #File
  #Ping
  #Pong
  #Name
  #Network_Password
  #None
EndEnumeration

#Port = 1340

Procedure.l AddPacketHeader(*buffer, header.l)
  
  PokeL(*buffer, header)
  
  ProcedureReturn *buffer
EndProcedure

Procedure.b SendPacket(hote.s, port.l, packet.l, length.l)
  conn = OpenNetworkConnection(hote, port, #PB_Network_UDP)
  ret.b = #False
  
  If conn
  
    SendNetworkData(conn, packet, length)
    CloseNetworkConnection(conn)
    
    ret = #True
    
  EndIf
    
  ProcedureReturn ret
EndProcedure


InitNetwork()


; Création du packet de données
*packet = AllocateMemory(9128)

; #Connect
; Format : CONNECT|REMOTE_SERVER_PORT(long)|NAME(str)|PASSWORD(str)

*packet = AddPacketHeader(*packet, #Connect)
PokeL(*packet + 4, #Port)

nom.s = "Toto@msn.com"


PokeL(*packet + 8, Len(nom)) 

PokeS(*packet + 12, nom, Len(nom))

If SendPacket("127.0.0.1", 1539, *packet, 12 + Len(nom))
  Debug "Envoi du packet OK"
Else
  Debug "Envoi du packet Echoue"
EndIf



; Création d'un packet CLIENT


*client_packet = AllocateMemory(9128)

; #Clients
; Format CLIENTS|NB_CLIENTS(long)|IP(long)|PORT(long)|NAME(str)|[...]

*client_packet = AddPacketHeader(*client_packet, #Clients)

PokeL(*client_packet + 4, #Port)

deb = *client_packet

nom1.s = "Nomde Test"
ip1.l = MakeIPAddress(127, 1, 1, 1)
port1.l = 10000

nom2.s = "Test n°2"
ip2.l = MakeIPAddress(80, 100, 245, 128)
port2.l = 20000

nom3.s = "AB  "
ip3.l = MakeIPAddress(254, 253, 252, 251)
port3.l = 30000

PokeL(*client_packet + 8, 3) ; Nombre de clients

PokeL(*client_packet + 12, ip1)
PokeL(*client_packet + 16, port1)
PokeL(*client_packet + 20, Len(nom1))
PokeS(*client_packet + 24, nom1)

PokeL(*client_packet + 25 + Len(nom1), ip2)
PokeL(*client_packet + 29 + Len(nom1), port2)
PokeL(*client_packet + 33 + Len(nom1), Len(nom2))
PokeS(*client_packet + 37 + Len(nom1), nom2)

PokeL(*client_packet + 38 + Len(nom1) + Len(nom2), ip3)
PokeL(*client_packet + 42 + Len(nom1) + Len(nom2), port3)
PokeL(*client_packet + 46 + Len(nom1) + Len(nom2), Len(nom3))
PokeS(*client_packet + 50 + Len(nom1) + Len(nom2), nom3)

SendPacket("127.0.0.1", 1539, *client_packet, 50 + Len(nom1) + Len(nom2) + Len(nom3)) 

; #Name
; Modification du nom d'un client
; Format NAME|REMOTE_SERVER_PORT(long)|NOM(str)


*name_packet = AllocateMemory(256)

*name_packet = AddPacketHeader(*name_packet, #Name)

nouveau_nom.s = "Ceci est un test !!!"

PokeL(*name_packet + 4, #Port)
PokeL(*name_packet + 8, Len(nouveau_nom))
PokeS(*name_packet + 12, nouveau_nom)

SendPacket("127.0.0.1", 1539, *name_packet, 12 + Len(nouveau_nom)) 



; #Disconnect
; Format : DISCONNECT|REMOTE_SERVER_PORT(long)

*remove_packet = AllocateMemory(64)
*remove_packet = AddPacketHeader(*remove_packet, #Disconnect)

PokeL(*remove_packet + 4, #Port)

SendPacket("127.0.0.1", 1539, *remove_packet, 8) 
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Petite explication :

Vous pouvez tester le premier source en lançant 2x (ou +) le premier code.
1. Vous lancer une première fois le programme (A) et démarrez le serveur
2. Vous lancer une seconde fois le programme (B) en prenant soin de modifier le port (Options > Serveur > Port d'écoute)
3. Vous connecter le second au premier (Amorçage > IP : localhost ; Port : [le port de A])
4. Les 2 sont maintenant connectés.

Pour corser un peu la chose vous pouvez lancer le second code qui vous permettra d'ajouter 3 clients factices (mais 1 se déconnectera [voir config]).

Un second cas d'utilisation est de lancer le code 1 puis le code 2 : cela aura pour effet d'ajouter des clients, et de tester le mécanisme CGC (Client Garbage Collector) qui supprime des clients s'ils sont inactifs.

J'espère être assez clair, c'est pas facile à expliquer ! :oops:
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

Tout d'abord merci de ce code de la mort 8O

Bon comme dab, la seule chose que j'ai compris, c'est PING-PONG car quand j'etais petit, moi aussi j'en faisais avec mes cousins sur une grande table verte et un filet au milieu :D

Fort de cette decouverte, j'ai démarré une fois le code, puis le test, et ça a marché nikel 8)

Comme tu dois t'en douter, c'est avec les 2 en meme temps que les atheniens s'ateignirent :oops:

J'ai lancé une premiere fois (A) et j'ai réglé l'ip local host 127.0.0.1 et mis un canal au hasard 50.

Avant de lancer le (B), j'ai modifié le canal ecoute comme tu l'as dit a 1540
J'ai lancé une 2e fois, j'ai réglé à nouveau l'ip local host 127.0.0.1 et mis le meme canal 50.
Et rien ne se passe :cry:
Peut etre parce que je suis sur la meme machine :roll:

Encore merci de ce voyage dans le monde de "l'ane"
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Message par Cls »

Tu peux lancer autant de fois que tu veux le programme sur ta machine.

As - tu modifier le source avant de le lancer (le port je veux dire) ? Le port se règle dans l'interface (Options > Serveur > Port d'écoute).

Comment as - tu dis au client B de se connecter au client A ? Es - tu passé par le cadre "Amorçage" ?

Je n'ai pas trop de temps tout de suite, j'ai referai une petite notice plus claire dans la matinée ;)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Message par Kwai chang caine »

Je sais, j'suis un boulet :oops:
Toi tu fait une ferrari et moi j'arrive meme pas à regler le siege :oops:

Application A
Cadre amorçage
IP = 127.0.0.1
Port = 50

Onglet serveur
Port d'ecoute = 1539

Application B
Cadre amorçage
IP = 127.0.0.1
Port = 50

Onglet serveur
Port d'ecoute = 1540

Et rien ne se passe :cry:
D'ailleur, je n'ai meme pas compris ce qui aurait du se passer ?? :oops:
Quand on ecris dans "salle commune" de l'un, ça ecris dans "salle comune" de l'autre ????
Répondre