La fonction OpenNetworkConnection(AdrIP$, PortC) est une véritable merveille. Mais.... elle bloque mon poste pendant 1 à 2 secondes s'il n'y a personne à AdrIP$.
Je comprends pourquoi : l'adresse est testée, puis re-testée, puis re-re-testée dans l'espoir que quelqu'un finisse pas répondre.
L'ennui, c'est que tout ça prend du temps. Moi, je voudrais faire une exploration de mon réseau pour voir qui est connecté, et cette méthode d'exploration est beaucoup trop lente.
Est-ce que quelqu'un sait :
1- s'il est possible de changer un paramètre pour que cette boucle d'attente soit moins longue
OU
2- qu'elles sont les fonctions API utilisées par OpenNetworkConnection (je n'ai pas réussi à trouver)
OpenNetworkConnection : Comment ça marche ?
OpenNetworkConnection : Comment ça marche ?
Tout obstacle est un point d'appui potentiel.
Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
ZapMan,
Utiliser l'API ne changera pas le fait qu'un timeout assez long est toujours nécessaire pour tester une connection.
Le truc à faire pour ne pas rester planté devant le PC pendant des heures si on veut tester une classe IP complète, c'est d'utiliser des threads ... il n' y a que ça !
Et alors là c'est tout de suite moins simple, bien sûr.
Entre autres parce que le multi-threading pose des tas de problèmes de fiabilité et de stabilité.
De plus, pour tester une suite d'adresses IP, il est nécessaire de créer une boucle qui fait varier les octets de l'adresse IP dans une incrémentation pas simple. En effet une adresse IP est une chaine de caractères (y compris pour la commande OpenNetworkConnection()), mais elle est constituée de valeurs octets non signés, dans l'ordre des poids croissants de gauche à droite.
Or chacun sait que les octets d'un entier long sont placés de droite à gauche etc ...
Donc faire une incrémentation d'une valeur dans une boucle ne marche pas pour pointer une série d'IPs successives.
Alors c'est le binz !
Bon mais, une fois résolus tous ces petits problèmes, on peut arriver à des résultats intéressants quand même.
Le code qui vient n'est pas commenté, mais bon !
Il reste quelques bugs dans la transmission des résultats au ListIcon, à cause du multi-threading que je ne maîtrise pas assez bien pour empêcher l'apparition intempestive de morceaux de chaines de caractères de temps en temps.
...
J'espère néanmoins que cela te donnera plein d'indications sur la méthode et les outils.
Je commenterai mieux ce code dans une prochaine version.
Utiliser l'API ne changera pas le fait qu'un timeout assez long est toujours nécessaire pour tester une connection.
Le truc à faire pour ne pas rester planté devant le PC pendant des heures si on veut tester une classe IP complète, c'est d'utiliser des threads ... il n' y a que ça !
Et alors là c'est tout de suite moins simple, bien sûr.
Entre autres parce que le multi-threading pose des tas de problèmes de fiabilité et de stabilité.
De plus, pour tester une suite d'adresses IP, il est nécessaire de créer une boucle qui fait varier les octets de l'adresse IP dans une incrémentation pas simple. En effet une adresse IP est une chaine de caractères (y compris pour la commande OpenNetworkConnection()), mais elle est constituée de valeurs octets non signés, dans l'ordre des poids croissants de gauche à droite.
Or chacun sait que les octets d'un entier long sont placés de droite à gauche etc ...
Donc faire une incrémentation d'une valeur dans une boucle ne marche pas pour pointer une série d'IPs successives.
Alors c'est le binz !
Bon mais, une fois résolus tous ces petits problèmes, on peut arriver à des résultats intéressants quand même.
Le code qui vient n'est pas commenté, mais bon !
Il reste quelques bugs dans la transmission des résultats au ListIcon, à cause du multi-threading que je ne maîtrise pas assez bien pour empêcher l'apparition intempestive de morceaux de chaines de caractères de temps en temps.
...
J'espère néanmoins que cela te donnera plein d'indications sur la méthode et les outils.
Je commenterai mieux ce code dans une prochaine version.
Code : Tout sélectionner
Enumeration
#Window_Main
#StatusBar
#Gadget_Text_Start
#Gadget_Text_End
#Gadget_Button_OK
#Gadget_Button_Cancel
#Gadget_IP_Start
#Gadget_IP_End
#Gadget_ListIcon
EndEnumeration
#MaxThreads = 1000
NewList Threads.l()
Global StartAddress.l, EndAddress.l, sStartAddress.s, sEndAddress.s
Global Run.l
Global TotalConnections.l, TotalThreads.l, CurrentConnection.s
Global OldTotalConnections.l, OldTotalThreads.l, OldCurrentConnection.s
Global hListIconGadget.l
Procedure UpdateListIcon(String.s)
EndProcedure
Procedure TestConnectionToIP(IPAddress.l)
sIPAddress.s = IPString(IPAddress)
#PING_TIMEOUT = 1000
strMessage.s
Echo.ICMP_ECHO_REPLY
EchoMessage.s = "Hello there " + Space(20)
tz = GetTickCount_()
hFile = IcmpCreateFile_()
lngResult = IcmpSendEcho_(hFile, IPAddress, EchoMessage, Len(EchoMessage), 0, Echo, SizeOf(ICMP_ECHO_REPLY), #PING_TIMEOUT)
If lngResult = 0
PingResult = Echo\Status * -1
Else
PingResult = Echo\RoundTripTime
EndIf
lngResult = IcmpCloseHandle_(hFile)
If PingResult >= 0
While WindowEvent() : Wend
CurrentConnection = "Scanning " + sIPAddress + " OK"
If CountList(Threads()) > #MaxThreads
While CountList(Threads()) > #MaxThreads / 2
ResetList(Threads())
NextElement(Threads())
WaitThread(Threads())
Sleep_(2500)
DeleteElement(Threads())
TotalThreads - 1
Wend
EndIf
AddGadgetItem(#Gadget_ListIcon, -1, sIPAddress + Chr(10) + Str(GetTickCount_() - tz))
While WindowEvent() : Wend
EndIf
TotalConnections - 1
TotalThreads - 1
EndProcedure
Procedure RunScan()
Sleep_(500)
StartAddress.l = GetGadgetState(#Gadget_IP_Start)
EndAddress.l = GetGadgetState(#Gadget_IP_End)
iStartAddress = IPAddressField(StartAddress, 0) << 24 + IPAddressField(StartAddress, 1) << 16 + IPAddressField(StartAddress, 2) << 8 + IPAddressField(StartAddress, 3)
iEndAddress = IPAddressField(EndAddress, 0) << 24 + IPAddressField(EndAddress, 1) << 16 + IPAddressField(EndAddress, 2) << 8 + IPAddressField(EndAddress, 3)
For iIPAddress = iStartAddress To iEndAddress
IPAddress = MakeIPAddress(IPAddressField(iIPAddress, 3), IPAddressField(iIPAddress, 2), IPAddressField(iIPAddress, 1), IPAddressField(iIPAddress, 0))
sIPAddress.s = IPString(IPAddress)
CurrentConnection = "Scanning " + sIPAddress
ParameterString.s = Str(IPAddress)
TotalConnections + 1
ThreadID = CreateThread(@TestConnectionToIP(), IPAddress)
TotalThreads + 1
Delay(50)
Next
Run = #FALSE
TotalThreads - 1
EndProcedure
Procedure Stop(ThreadID)
Run = #FALSE
CurrentConnection = "Canceling ..."
If ThreadID <> 0
CurrentConnection = "Canceling " + Str(ThreadID)
KillThread(ThreadID)
TotalThreads - 1
EndIf
ResetList(Threads())
While NextElement(Threads())
CurrentConnection = "Canceling " + Str(Threads())
KillThread(Threads())
TotalThreads - 1
Wend
ClearList(Threads())
CurrentConnection = "Done"
EndProcedure
Procedure DoWeRun(ThreadID.l)
If ThreadID <> 0
Stop(ThreadID)
SendMessage_(hListIconGadget, #LVM_DELETEALLITEMS, 0, 0)
EndIf
Run = #TRUE
CurrentConnection = "Scanning ..."
ThreadID = CreateThread(@RunScan(), 0)
TotalThreads + 1
ProcedureReturn ThreadID
EndProcedure
;
;
;
sStartAddress.s = "194.79.120.0"
sEndAddress.s = "194.79.120.255"
StartAddress.l
EndAddress.l
Quit = #FALSE
Run = #FALSE
WindowXSize = 640
WindowYSize = 480
If InitNetwork()
If OpenWindow(#Window_Main, 0, 0, WindowXSize, WindowYSize, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Ip sniffer")
AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Escape, #PB_Shortcut_Escape)
AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Return, #PB_Shortcut_Return)
AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Delete, #PB_Shortcut_Delete)
If CreateStatusBar(#StatusBar, WindowID())
AddStatusBarField(400)
AddStatusBarField(120)
AddStatusBarField(120)
EndIf
If CreateGadgetList(WindowID(0))
TextGadget(#Gadget_Text_Start, 10, 10, 80, 20, "Start address")
TextGadget(#Gadget_Text_End, 10, 30, 80, 20, "End address")
ButtonGadget(#Gadget_Button_OK, 230, 10, 60, 20, "Go")
ButtonGadget(#Gadget_Button_Cancel, 230, 30, 60, 20, "Cancel")
IPAddressGadget(#Gadget_IP_Start, 100, 10, 120, 20)
IPAddressGadget(#Gadget_IP_End, 100, 30, 120, 20)
hListIconGadget = ListIconGadget(#Gadget_ListIcon, 10, 50, WindowXSize - 20, WindowYSize - 80, "Server found", 120)
AddGadgetColumn(#Gadget_ListIcon, 1, "Time", 80)
EndIf
SetGadgetState(#Gadget_IP_Start, MakeIPAddress(Val(StringField(sStartAddress, 1, ".")), Val(StringField(sStartAddress, 2, ".")), Val(StringField(sStartAddress, 3, ".")), Val(StringField(sStartAddress, 4, "."))))
SetGadgetState(#Gadget_IP_End, MakeIPAddress(Val(StringField(sEndAddress, 1, ".")), Val(StringField(sEndAddress, 2, ".")), Val(StringField(sEndAddress, 3, ".")), Val(StringField(sEndAddress, 4, "."))))
StartAddress = GetGadgetState(#Gadget_IP_Start)
EndAddress = GetGadgetState(#Gadget_IP_End)
Repeat
Select WindowEvent()
Case #PB_Event_CloseWindow
Quit = #TRUE
Case #PB_Event_Menu
Select EventMenuID()
Case #PB_Shortcut_Escape
If Run
Stop(ThreadID)
Else
Quit = #TRUE
EndIf
Case #PB_Shortcut_Return
ThreadID = DoWeRun(ThreadID)
Case #PB_Shortcut_Delete
Stop(ThreadID)
EndSelect
Case #PB_Event_Gadget
Select EventGadgetID()
Case #Gadget_IP_Start
sStartAddress = GetGadgetText(#Gadget_IP_Start)
StartAddress = GetGadgetState(#Gadget_IP_Start)
Case #Gadget_IP_End
sEndAddress = GetGadgetText(#Gadget_IP_End)
EndAddress = GetGadgetState(#Gadget_IP_End)
Case #Gadget_Button_OK
ThreadID = DoWeRun(ThreadID)
Case #Gadget_Button_Cancel
Stop(ThreadID)
EndSelect
EndSelect
If OldCurrentConnection <> CurrentConnection
OldCurrentConnection = CurrentConnection
StatusBarText(#StatusBar, 0, CurrentConnection)
EndIf
If OldTotalConnections <> TotalConnections
OldTotalConnections = TotalConnections
StatusBarText(#StatusBar, 1, Str(TotalConnections))
EndIf
If OldTotalThreads <> TotalThreads
OldTotalThreads = TotalThreads
StatusBarText(#StatusBar, 2, Str(TotalThreads))
EndIf
Sleep_(1)
Until Quit
Stop(ThreadID)
EndIf
EndIf
TerminateProcess_(GetCurrentProcess_(), 0)
End
Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
Super ! C'est quand même beaucoup plus rapide qu'avec la fonction PB. Ca répond pile poil à mon besoin (je dois scanner mon réseau d'entreprise pour savoir qui est connecté et je n'ai qu'une petite plage d'adresses à explorer).
Merci d'avoir répondu aussi vite et aussi bien.
Merci d'avoir répondu aussi vite et aussi bien.

Tout obstacle est un point d'appui potentiel.
Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
Comme on dit :
le code qui compile, c'est bien plus facile, et plus rigolo, que le code qu'est pas beau !
Ben je suis bien content de t'avoir rendu service.
Si tu l'utilises mon programme, tu mets mon nom dedans, comme ça on ne m'oublieras plus jamais
le code qui compile, c'est bien plus facile, et plus rigolo, que le code qu'est pas beau !
Ben je suis bien content de t'avoir rendu service.
Si tu l'utilises mon programme, tu mets mon nom dedans, comme ça on ne m'oublieras plus jamais

Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.