Detecter une application server sur le reseau local

Sujets variés concernant le développement en PureBasic
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Detecter une application server sur le reseau local

Message par Cls »

Ce sera pour demain ;)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: Detecter une application server sur le reseau local

Message par Thyphoon »

Cls a écrit :Ce sera pour demain ;)
Pas de souci !! :P
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Detecter une application server sur le reseau local

Message par Cls »

Code : Tout sélectionner

; ______________________________________________________________________________
;
; Module permettant de scanner le réseau local à la recherche d'un hote ayant 
; un port donné ouvert (recherche de serveur).
; 
; Programme multi threadé, permettant d'accélérer la recherche.
; 
; Modifier la variable TIMEOUT pour accélérer la recherche.
; Modifier la variable MAX_RUNNING_THREAD pour augmenter le nombre de thread simultané
; Compatible réseau Microsoft uniquement.
; Utilise les APIs Windows.
; Sans interface graphique ;) Utiliser le debugguer pour voir les résultats
;
; Compilé sous version 4.40 b5
;
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

;- Structures internes
; __________________________________________
Structure CONNECT_INFO
  host.s{100}
  port.l
  type.l ; TCP ou UDP  
EndStructure

Structure RUNNING_THREAD
  thread_id.l
  ms_debut.l
  host.s{100}
  port.l
EndStructure

Structure SERVER_INFO_101 
 dwPlatformId.l 
 lpszServerName.l 
 dwVersionMajor.l 
 dwVersionMinor.l 
 dwType.l 
 lpszComment.l 
EndStructure 

Structure LAN_RESULT 
 Name.s 
 IP_Name.s 
 Aktiv_Server.l
 Spiel_Name.s 
 Spieler_bisher.l 
EndStructure 
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

;- Listes chainées
Global NewList TabThread.RUNNING_THREAD()

Global NewList LAN_Client.LAN_RESULT() 


;- Variables globales
Global current_running_thread
Global SEM_SCAN_CURRENT_THREAD
Global MAX_RUNNING_THREAD = 50
Global TIMEOUT = 50 ; en millisecondes
Global PORT = 1025 ; Port à rechercher


;-------------------  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  ---------------------


;- Constantes
#MAX_PREFERRED_LENGTH = -1 
#NERR_SUCCESS         = 0 
#ERROR_MORE_DATA      = 234 
#MainWindow           = 100 
#MMTB                 = 200 


;- Procédures et fonctions
; __________________________________________
Procedure.s GetIPbyName (NameIP.s) 
  TheIPAdress.s 
  pHostinfo = gethostbyname_(NameIP) ; /!\ Fonction lente => A threader pour améliorer les performances
  
  If pHostinfo = 0 
    TheIPAdress = "Unable to resolve domain name" 
  Else 
  
    CopyMemory (pHostinfo, hostinfo.HOSTENT, SizeOf(HOSTENT)) 
    
    If hostinfo\h_addrtype <> #AF_INET 
      MessageRequester("Info","A non-IP address was returned",0) 
    Else 
      While PeekL(hostinfo\h_addr_list+AdressNumber*4) 
        ipAddress = PeekL(hostinfo\h_addr_list+AdressNumber*4) 
        TheIPAdress = StrU(PeekB(ipAddress),0)+"."+StrU(PeekB(ipAddress+1),0)+"."+StrU(PeekB(ipAddress+2),0)+"."+StrU(PeekB(ipAddress+3),0) 
        AdressNumber+1 
      Wend 
    EndIf 
  EndIf 
  
  ProcedureReturn TheIPAdress 
EndProcedure 

Procedure GetLANList(type.l) 
  IPResult.s 
  se101.SERVER_INFO_101 
  nStructSize = SizeOf(SERVER_INFO_101) 
  
  RetCode = NetServerEnum_(0, 101, @bufptr, #MAX_PREFERRED_LENGTH, @dwEntriesread, @dwTotalentries, type, 0, @dwResumehandle) 
  
  If RetCode = #NERR_SUCCESS And RetCode <> #ERROR_MORE_DATA 
    
    For i = 0 To dwEntriesread - 1 
      
      CopyMemory( bufptr + (nStructSize * i),@se101, nStructSize) 
      
      Buffer.s=Space(512) 
      result=WideCharToMultiByte_(#CP_ACP, 0, se101\lpszServerName, 255, @Buffer.s, 512, 0, 0) 
      ;IPResult = GetIPbyName (Buffer) ; /!\ Fonction lente => On la zappe car le nom d'hôte nous suffit ;)
      
      Debug Buffer + " => " + IPResult
      
      AddElement(LAN_Client()) 
        LAN_Client()\Name = Buffer 
        LAN_Client()\IP_Name = IPResult 
    Next 
    
  Else 
    MessageRequester("Info","Failed",0) 
  EndIf 
  
  NetApiBufferFree_(bufptr) 
EndProcedure  


Procedure connect_thread (connect_info_.l)
  
  *connect_info.CONNECT_INFO = connect_info_ 
  
  con = OpenNetworkConnection(*connect_info\host, *connect_info\port, *connect_info\type)

  If con
    
    Debug *connect_info\host + " -------------------------- > " + Str(*connect_info\port) + " is open !"    
    ;AddGadgetItem(ports, -1, Str(*connect_info\port) + Chr(10) + "Open")
    
    CloseNetworkConnection(con)
  
  Else
    
    Debug "Le port " + Str(*connect_info\port) + " ne répond pas sur " + *connect_info\host
    
  EndIf
  
  FreeMemory(*connect_info)
  
  Global current_running_thread
  Sem_Acquire(SemCurrentThreadRunning)
  current_running_thread - 1
  Sem_Release(SemCurrentThreadRunning)
  
  ProcedureReturn 
  
EndProcedure

Procedure.l ScanLanThread(port.l)
  
  ForEach LAN_Client()

    struct = AllocateMemory(SizeOf(CONNECT_INFO))
    *connect_info.CONNECT_INFO = struct
  
    *connect_info\host = Lan_Client()\Name
    *connect_info\port = port
    *connect_info\type = #PB_Network_TCP
    
    
    AddElement(TabThread())
    TabThread()\thread_id = CreateThread(@connect_thread(), *connect_info)
    TabThread()\ms_debut = ElapsedMilliseconds()
    TabThread()\host = Lan_Client()\Name
    TabThread()\port = port
    
    ; Ajout un thread
    Sem_Acquire(SemCurrentThreadRunning)
    current_running_thread + 1
    Sem_Release(SemCurrentThreadRunning)
    
    ; Synchro
    While current_running_thread >= MAX_RUNNING_THREAD
      
      ; Vérifie qu'un ou plusieurs thread n'a pas dépassé le time out. Si c'est le cas  => on le supprime
      ForEach TabThread()
        
        If ElapsedMilliseconds() - TabThread()\ms_debut > TIMEOUT
          
          If IsThread(TabThread()\thread_id)
            
            PauseThread(TabThread()\thread_id)
            KillThread(TabThread()\thread_id)
            

            Debug "Le port " + Str(TabThread()\port) + " ne répond pas sur " + TabThread()\host
            
            DeleteElement(TabThread())
            
            Sem_Acquire(SemCurrentThreadRunning)
            current_running_thread - 1
            Sem_Release(SemCurrentThreadRunning)
          
          Else
            
            DeleteElement(TabThread())
          
          EndIf
        EndIf
        
      Next
      
      Delay(1)
      
    Wend
    
    Delay(15)
    
  Next
  
  
  ; Attends jusqu'à ce que tous les thread se terminent
  While CountList(TabThread()) > 0
    
    ForEach TabThread()
        
        If ElapsedMilliseconds() - TabThread()\ms_debut > TIMEOUT
          
          If IsThread(TabThread()\thread_id)
            KillThread(TabThread()\thread_id)
            
            Debug "Le port " + Str(TabThread()\port) + " ne répond pas sur " + TabThread()\host
          
          EndIf
          
          ; Suppression de l'élement
          DeleteElement(TabThread())  
            
          
          Sem_Acquire(SemCurrentThreadRunning)
          current_running_thread - 1
          Sem_Release(SemCurrentThreadRunning)
          
        EndIf
        
      Next
    
    Delay(05)
  Wend

EndProcedure


; Initialise le réseau
InitNetwork()

; Scan le réseau
; Le paramètre correspond au type de matériel à scanner
; Les valeurs possibles sont :
; SV_TYPE_WORKSTATION => All workstations.
; SV_TYPE_SERVER => All computers that run the Server service.
; SV_TYPE_SQLSERVER => Any server that runs Microsoft SQL Server.
; SV_TYPE_DOMAIN_CTRL => A server that is primary domain controller.
; SV_TYPE_DOMAIN_BAKCTRL => Any server that is a backup domain controller.
; SV_TYPE_TIME_SOURCE => Any server that runs the Timesource service.
; SV_TYPE_AFP => Any server that runs the Apple Filing Protocol (AFP) file service.
; SV_TYPE_NOVELL => Any server that is a Novell server.
; SV_TYPE_DOMAIN_MEMBER => Any computer that is LAN Manager 2.x domain member.
; SV_TYPE_LOCAL_LIST_ONLY => Any computer maintained in a list by the browser. See the following Remarks section.
; SV_TYPE_PRINTQ_SERVER => Any computer that shares a print queue.
; SV_TYPE_DIALIN_SERVER => Any server that runs a dial-in service.
; SV_TYPE_XENIX_SERVER => Any server that is a Xenix server.
; SV_TYPE_SERVER_MFPN => Any server that runs the Microsoft File And Print For NetWare service.
; SV_TYPE_NT => A workstation Or server.
; SV_TYPE_WFW => Any computer that runs Windows For Workgroups.
; SV_TYPE_SERVER_NT => Any server that is Not a domain controller.
; SV_TYPE_POTENTIAL_BROWSER => Any computer that can run the browser service.
; SV_TYPE_BACKUP_BROWSER => A computer that runs a browser service As backup.
; SV_TYPE_MASTER_BROWSER => A computer that runs the master browser service.
; SV_TYPE_DOMAIN_MASTER => A computer that runs the domain master browser.
; SV_TYPE_DOMAIN_ENUM => The primary domain.
; SV_TYPE_WINDOWS => A computer that runs Windows.
; SV_TYPE_ALL => All servers.
; SV_TYPE_TERMINALSERVER => A server running the Terminal Server service.
; SV_TYPE_CLUSTER_NT => Server clusters available in the domain.
; SV_TYPE_CLUSTER_VS_NT => Cluster virtual servers available in the domain.
#SV_TYPE_ALL               = $FFFFFFFF
#SV_TYPE_UNKNOWN           = $1F000000

#SV_TYPE_DOMAIN_ENUM       = $80000000
#SV_TYPE_LOCAL_LIST_ONLY   = $40000000
#SV_TYPE_ALTERNATE_XPORT   = $20000000
#SV_TYPE_DFS_SERVER        = $00800000
#SV_TYPE_WIN95_PLUS        = $00400000
#SV_TYPE_SERVER_VMS        = $00200000
#SV_TYPE_SERVER_OSF        = $00100000
#SV_TYPE_DOMAIN_MASTER     = $00080000
#SV_TYPE_MASTER_BROWSER    = $00040000
#SV_TYPE_BACKUP_BROWSER    = $00020000
#SV_TYPE_POTENTIAL_BROWSER = $00010000
#SV_TYPE_SERVER_NT         = $00008000
#SV_TYPE_SERVER_MFPN       = $00004000
#SV_TYPE_WFW               = $00002000
#SV_TYPE_NT                = $00001000
#SV_TYPE_SERVER_UNIX       = $00000800
#SV_TYPE_DIALIN_SERVER     = $00000400
#SV_TYPE_PRINTQ_SERVER     = $00000200
#SV_TYPE_DOMAIN_MEMBER     = $00000100
#SV_TYPE_NOVELL            = $00000080
#SV_TYPE_AFP               = $00000040
#SV_TYPE_TIME_SOURCE       = $00000020
#SV_TYPE_DOMAIN_BAKCTRL    = $00000010
#SV_TYPE_DOMAIN_CTRL       = $00000008
#SV_TYPE_SQLSERVER         = $00000004
#SV_TYPE_SERVER            = $00000002
#SV_TYPE_WORKSTATION       = $00000001

GetLANList(#SV_TYPE_ALL) 

; La liste chainée LAN_Client est désormais à jour
; On lance un thread pour trouver si un serveur tourne sur ces clients

ScanLanThread(PORT)
 
Dernière modification par Cls le jeu. 22/oct./2009 11:16, modifié 1 fois.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: Detecter une application server sur le reseau local

Message par Thyphoon »

super je vais testé ça des que j'ai 2 minutes ... :P
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Detecter une application server sur le reseau local

Message par Cls »

Je viens de retester, il doit y avoir un bug. Je corrige et je reposte ;)

EDIT : précédent post mis à jour ;)
Avatar de l’utilisateur
Le psychopathe
Messages : 764
Inscription : jeu. 03/mars/2005 19:23

Re: Detecter une application server sur le reseau local

Message par Le psychopathe »

J'ai vérifié ton code et je l'ai testé sur le réseau de mon taf , il me liste bien tous les noms des pc. Quelques milliers ...
merci ^^
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Detecter une application server sur le reseau local

Message par Cls »

Pas de souci, si ça peut servir, autant partager ;)

Le code ne propose pas d'exploitation directe sans modification mais c'est très facile à ajouter. Juste déclarer une liste chainée globale et le tour est joué ;)

@Typhoon : une fois une liste d'hôte avec ton port ouvert, je te conseille de vérifier qu'il s'agit bien du serveur visé en mettant en place un petit protocole d'identification entre client et serveur, mais tu as surement prévu le coup.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: Detecter une application server sur le reseau local

Message par Thyphoon »

j'ai testé ça marche super ! me reste plus qu'a intégré ça a mon jeu !! :)
Merci beaucoup
Et juste une petite question. Les fonctions :

Code : Tout sélectionner

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
on peut pas les remplacer part les fonctions intégré au purebasic ?
Cls
Messages : 620
Inscription : mer. 22/juin/2005 8:51
Localisation : Nantes

Re: Detecter une application server sur le reseau local

Message par Cls »

Oui il doit être possible (et conseillé) d'utiliser les fonction natives CreateSemaphore & Co. Je ne les ai pas utilisées car j'ai copié/collé du code fait sur une version de PB où elles n'existaient pas encore (4.30, elles ne sont apparues qu'en 4.31).
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: Detecter une application server sur le reseau local

Message par Thyphoon »

Merci pour ta réponse (et surtout pour ton code)
ça les sémaphores, j'avoue que j'ai toujours pas comprit c'est comme les mutexs, j'ai toujours pas vraiment compris a quoi ça servait ni comment les utiliser. :P Faudra que je me penche un jour sérieusement dessus !

En tout cas ton code marche super !
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: Detecter une application server sur le reseau local

Message par Thyphoon »

ça marche super au boulot ! mais chez moi j'ai un "Failed" ! Est-ce du a la différence entre un reseau grand-public (workgroup) et un reseau d'entreprise avec domaine ?
Répondre