Ping

04/23/2013 17:36 Achat#1
Hi epvp!

Wie im AutoIt Tratsch Thread schon beschrieben, möchte ich mit AutoIt eine größere Anzahl an IPs (Proxyserver) anpingen und das möglichst schnell.

Code:
Func _Ping($sIP, $iTimeout = 5096)
	Local Const $iThreads = 300
	Local $aProcessList = ProcessList('cmd.exe')
	If $aProcessList[0][0] >= $iThreads Then
		Do
			Sleep(100)
			$aProcessList = ProcessList('cmd.exe')
		Until $aProcessList[0][0] <= $iThreads
	EndIf
	Local $sCommand = '1>> "' & $sIP & '.txt" ping ' & $sIP & ' /n 1 /w ' & $iTimeout
	ShellExecute(@ComSpec, " /C " & $sCommand, @TempDir, 'open', @SW_HIDE)
	Return '%PING%' & $sIP & '%PING%'
EndFunc   ;==>_Ping

Func _PingResult($sIP)
	Local $sResult = FileRead(@TempDir & '\' & $sIP & '.txt')
	Local $aRegExp = StringRegExp($sResult, 'Mittelwert = (\d+)ms', 3)
	FileDelete(@TempDir & '\' & $sIP & '.txt')
	If IsArray($aRegExp) Then Return $aRegExp[0]
	Return 'Timeout'
EndFunc   ;==>_PingResult
Egal ob ich nun mehrere Autoit Scripte laufen habe, die [Only registered and activated users can see links. Click Here To Register...] ausführen, oder ob ich das via CMD.exe ping > file.txt mache, es bleibt immer ein Problem: 90%+ der Proxy Server sind nicht erreichbar. Wenn ich aber immer nur einen Ping Befehl nacheinander ausführe (For Schleife Array), dann funktionieren wesentlich mehr Proxys. Nur dauert das anpingen dann auch dementsprechend länger :(

Hat jemand eine Idee, an was das liegt und wie ich möglichst schnell viele IPs gleichzeitig anpingen kann?

Ziel ist, meine Proxyliste schneller aktualisieren zu können: [Only registered and activated users can see links. Click Here To Register...]

MfG
04/23/2013 18:31 butter123#2
[Only registered and activated users can see links. Click Here To Register...]
vllt kannste damit noch was anstellen.
04/23/2013 18:40 Achat#3
Da gibts Bann bei zu vielen Anfragen. Ich möchte soweit es geht auf fremde externe Seiten verzichten, da die meine Proxys dann in ihre eigene DB loggen könnten.
Außerdem muss der Rückgabewert auch wieder ausgelesen werden. Ich denke nicht, dass die 300 gleichzeitige Verbindungen zulassen werden, DNS/Whois lookups sind bei dieser Seite z.B. nur ~10 / Minute / IP möglich.

MfG
04/23/2013 18:41 expo_botter#4
ich empfehle dir CoProc.au3 damit kannst du viele au3-scripte starten.
und dazu diese 2 funktionen
PHP Code:
Func _ProcessGetHandle($iPID)
    
Local Const $PROCESS_QUERY_INFORMATION 0x0400
    Local $avRET 
DllCall("kernel32.dll""ptr""OpenProcess""int"$PROCESS_QUERY_INFORMATION"int"0"int"$iPID)
    If @
error Then
        
Return SetError(100)
    Else
        Return 
$avRET[0]
    EndIf
EndFunc   ;==>_ProcessGetHandle

Func ProcessGetExitCode
($hProc)

    
Local $t_ExitCode DllStructCreate("int")
    
Local $avRET DllCall("kernel32.dll""int""GetExitCodeProcess""ptr"$hProc"ptr"DllStructGetPtr($t_ExitCode))
    If @
error Then
        
Return SetError(100)
    Else
        Return 
DllStructGetData($t_ExitCode1)
    EndIf
EndFunc   ;==>ProcessGetExitCode 
du startest einfach eine Ping Funktion und lässt das Programm damit beenden z.b. Exit Ping("www.google.de")

allerdings ist anpingen von den Proxyservern sehr ungenau weshalb ich dir WinHTTP ans Herz lege (ich habe damals auch so meine Proxies gecheckt)
04/23/2013 18:43 Achat#5
Wie oben beschrieben führen gleichzeitige Ping-Anfragen zu einer hohen Fehlerquote.

Wie machst du das mit Winhttp?

MfG
04/23/2013 18:48 lolkop#6
Quote:
Originally Posted by Achat View Post
Hat jemand eine Idee, an was das liegt und wie ich möglichst schnell viele IPs gleichzeitig anpingen kann?
das problem hier liegt darinn, das pings ja über das icmp protokoll, und nicht etwa wie website aufrufe über tcp laufen...

da es leider keine icmp implementation in autoit gibt, müssten wir auf die icmp.dll zurückgreifen. diese hat in ihrer methode aber bereits eine schleife implementiert, welche auf ein ergebnis wartet, sodass hier keine "quasi-parallel" abarbeitung möglich ist...

die frage, welche sich hier aber eigentlich stellt ist: wozu einen server pingen, wenn man auch viel einfacher direkt einen verbindungstest via tcp protokoll starten kann?

Quote:
Originally Posted by butter123 View Post
[Only registered and activated users can see links. Click Here To Register...]
vllt kannste damit noch was anstellen.
nur weil ein server in der lage ist, eine ip zu erreichen, heist das noch lange nicht, das auch du in der lage bist diese ip zu erreichen :P
04/23/2013 18:51 expo_botter#7
die einzelnen Funktionen für WinHTTP gibts via google. Ich habe mein eigenes WinHTTP-Extended UDF geschrieben und bei mir würde es so aussehen.

PHP Code:
Func Check($proxy)
    
$handle HTTP_Startup()
    
HTTP_SetProxy($handle,$proxy)
    
HTTP_Timouts($handle,30000)
    
$Source HTTP_Request($handle,"http://www.elitepvpers.com/")
    If 
StringInStr($Source,'Aktuelle News</a></h2>'Then Exit 0
    
Exit 1
EndFunc 
Aufrufbar mittels:
PHP Code:
$PID[$i] = _CoProc("Check",$save[$i])
$Handle[$i] = _ProcessGetHandle($PID[$i])

While 
ProcessExists($PID[$i])
Sleep(100)
WEnd

If ProcessGetExitCode($PID[$i]) = 1 Then 
;Proxy down
Else
;
Proxy alive
EndIf 
so oder so ähnlich kann es aussehen
04/23/2013 18:52 Achat#8
Quote:
Originally Posted by lolkop View Post
diese hat in ihrer methode aber bereits eine schleife implementiert, welche auf ein ergebnis wartet, sodass hier keine "quasi-parallel" abarbeitung möglich ist...
Danke für die Aufklärung :)

Quote:
Originally Posted by lolkop View Post
viel einfacher direkt einen verbindungstest via tcp protokoll starten kann?
TcpConnect ?
Was stellst du dir darunter vor?

MfG
04/23/2013 18:56 expo_botter#9
Problem an dem bloßen Connecten ist das manche Proxies alive sind aber man keine requests ausführen darf, weshalb es auch wieder ungenau ist. Am besten ist ein Direkttest auf der Seite wo du die Proxies nutzen willst.


lolkop meint denke sowas:
PHP Code:
TCPStartup()
$socket TCPConnect($ip,$port)
If 
$socket = -1 Then
    
;Proxy down
Else
    ;
Proxy alive
    TCPCloseSocket
($socket)
EndIf
TCPShutdown() 
04/23/2013 19:00 lolkop#10
die frage ist ja, was du dir in deiner liste erwünschst...

der vorteil am direkten verbindungsversuch ist, du kannst genauer scannen als ein einfacher ping befehl und siehst so beispielsweise sofort ob auch der angegebene port tatsächlich frei ist.
da du nicht auf antworten warten musst, bist du auch in jedem falle deutlich schneller, als ein ping es je sein könnte...

der nachteil ist aber, das du keine reaktionszeit bekommst, und somit keine aussage über die qualität der verbindung treffen kannst.

ein einfaches beispiel, welches mal den ersten und letzten eintrag aus deiner liste testet (da der letzte gleich ein beispiel für einen nicht funktionierenden proxi ist):
Code:
TCPStartup()
ConsoleWrite(TCPConnect("194.110.219.20", 3129)&'  '&@error&@CRLF)
ConsoleWrite(TCPConnect("118.123.206.25", 80)&'  '&@error&@CRLF)
TCPShutdown()
wie du erkennen wirst, gibt es auch in der tcpconnect funktion eine schleife mit timeout. du hast aber direkt den vorteil, das du über @error direkt an den fehler kommst ([Only registered and activated users can see links. Click Here To Register...])

Edit:
Quote:
Originally Posted by expo_botter View Post
Problem an dem bloßen Connecten ist das manche Proxies alive sind aber man keine requests ausführen darf, weshalb es auch wieder ungenau ist. Am besten ist ein Direkttest auf der Seite wo du die Proxies nutzen willst.
ein proxy auf den man keine requests über den gegeben port laufen lassen darf ist absolut nutzlos...

die einzige möglichkeit der nutzung wäre gegeben, wenn tatsächlich nur das tcp protokoll blockiert wird, was ja immernoch protokolle wie smtp, ... ermöglichen würde...
auch in diesem falle kann man aber über die wsa fehlermeldung ermitteln, das tcp connects nicht erlaubt sind.
04/23/2013 19:00 Achat#11
Quote:
Originally Posted by expo_botter View Post
Problem an dem bloßen Connecten ist das manche Proxies alive sind aber man keine requests ausführen darf, weshalb es auch wieder ungenau ist. Am besten ist ein Direkttest auf der Seite wo du die Proxies nutzen willst.
Mach das mal bei 20k Proxies ^^
Es muss schnell gehen, ob ein spezieller Proxy wirklich funktioniert oder nicht kann dann ja bei Bedarf getestet werden. Beziehungsweise beim ersten Einsatz des Proxys.

MfG
04/23/2013 19:03 expo_botter#12
20k Proxies mit light-scan mittels tcpconnect und deep-scan mittels request dauert viellei 10-20 minuten mit nem au3 script und ner guten leitung.
04/24/2013 20:34 Achat#13
Quote:
Originally Posted by lolkop View Post
da du nicht auf antworten warten musst, bist du auch in jedem falle deutlich schneller, als ein ping es je sein könnte...
Dankeschön. TCPConnect funktioniert soweit auch ganz gut, schneller als Ping und auch mit Multitasking. Es gibt da jetzt nur noch ein Problem: Wenn der Host nicht erreichbar ist, dann verzögert das die Ausführung des TCPConnect Befehls sehr stark. Wie ich hier [Only registered and activated users can see links. Click Here To Register...] gelesen habe, lässt sich dieses Problem nicht beheben.

Hier mal mein Script (Ausschnitt):

Code:
If $CMDLINE[0] = 1 Then Exit FileWrite(@TempDir & '\' & StringReplace($CMDLINE[1], ':', '') & '.txt', _ProxyIsUp($CMDLINE[1]))

;Proxygrabber func // Achtung Pseudocode zur Veranschaulichung der wesentlichen Funktion

for $aProxylist = 0 to Ubound($aProxylist)-1
_ProxyIsUpExternal($aProxylist) ; Script mit Parametern starten, IP:Port Proxy überprüfen
next

for $aProxylist = 0 to Ubound($aProxylist)-1
$sHTML&=_ProxyIsUpExternalGetResult($aProxylist) ; Ergebnis des Proxytests aus Datei auslesen
next

; ...

Func _ProxyIsUp($sIPPort)
	Local $aIP = StringRegExp($sIPPort, '(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\:(\d+)', 3)
;$aIP[0] = IP
$aIP[1] = Port
	If IsArray($aIP) Then
		If $CMDLINE[0] Then _IPGetCountry($aIP[0])
		Local $sDownload, $iPing = TimerInit()
		If TCPConnect($aIP[0], $aIP[1]) > 0 Then
			$hSession = _WinHttpOpen('Mozilla/4.0')
			$tProxyInfo = _WinHttpProxyInfoCreate($WINHTTP_ACCESS_TYPE_NAMED_PROXY, $aIP[0] & ':' & $aIP[1], "localhost")
			_WinHttpSetOption($hSession, $WINHTTP_OPTION_PROXY, $tProxyInfo[0])
			$hConnect = _WinHttpConnect($hSession, 'api.hostip.info')
			$iPing = TimerInit()
			$sDownload = _WinHttpSimpleRequest($hConnect, 'GET', '/get_html.php?ip=')
			$iPing = Round(TimerDiff($iPing))
			_WinHttpCloseHandle($hConnect)
			_WinHttpCloseHandle($hSession)
			If StringRegExp($sDownload, 'IP: \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') Then
				If $iPing < 260 Then Return '<font color="#00FF00">' & $iPing & '</font>'
				If $iPing >= 5200 Then Return '<font color="#990000">' & $iPing & '</font>'
				If $iPing >= 1300 Then Return '<font color="#FF6600">' & $iPing & '</font>'
				If $iPing >= 500 Then Return '<font color="#FFCC00">' & $iPing & '</font>'
			EndIf
		EndIf
	EndIf
	Return '<font color="#FF0000"><span style="display:none">9999999</span>Offline</font>'
EndFunc   ;==>_ProxyIsUp

Func _ProxyIsUpExternal($sIPPort)
	Local Const $iThreads = 49
	Local $aProcessList = ProcessList(@ScriptName)
	If $aProcessList[0][0] >= $iThreads Then
		Do
			Sleep(10)
			$aProcessList = ProcessList(@ScriptName)
		Until $aProcessList[0][0] <= $iThreads
	EndIf
	Run(@ScriptFullPath & ' ' & $sIPPort, @TempDir, @SW_HIDE)
	Return '%PING%' & $sIPPort & '%PING%'
EndFunc   ;==>_ProxyIsUpExternal

Func _ProxyIsUpExternalGetResult($sIPPort)
	Local $sReturn = FileRead(@TempDir & '\' & StringReplace($sIPPort, ':', '') & '.txt')
	FileDelete(@TempDir & '\' & StringReplace($sIPPort, ':', '') & '.txt')
	Return $sReturn
EndFunc   ;==>_ProxyIsUpExternalGetResult
Etwa so ist mein Programm aufgebaut, wenn es Fragen zum Code gibt, bitte ich diese zu stellen ;)
Verbesserungsvorschläge etc. sind willkommen, AutoIt Multitasking ist eben doch nicht allzu ressourcenschonend...

Die IP-Seite (api.hostip.info) werde ich später noch durch eine Seite ersetzen, die mir den Proxytyp ausgibt (anonym/transparent/elite), ein weglassen des Seitendownloads ist daher eher keine Option.

MfG und vielen Dank für die rege Beteiligung am Thread. :*