UDP-Broadcast - Problem Source-Port

  • Hallo Zusammen,
    ich möchte gerne von einem bestimmten Netzwerktelnehmer die IP-Adresse über ein UDP-Brodcast bekommen.

    Über die Orginalsoftware des Hersteller habe ich über einen Netzwerk-Sniffer ausglesen wie dieser den UDP-Brodcast absetzt.
    Es wird über die IP "255.255.255.255" an den Port "30718" über das UDP-Protokoll der Hex-Wert "0x000000F6" gesendet. Darauf antwortet der Netzwerktelnehmer.

    Das Absetzen des Hex-Wert "0x000000F6" über das UDP-Protokoll in AutoIt:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <String.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $port2 = 30718
    $ip_Global = "255.255.255.255"

    [/autoit] [autoit][/autoit] [autoit]

    UDPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    $socket2 = UDPOpen ($ip_Global, $port2 ,1)
    If @error <> 0 Then
    MsgBox(0, "Error UDPOpen", "Errornummer: " & @error)
    Exit
    EndIf
    $UDPSend = UDPSend($socket2, _HexToString("000000F6"))

    [/autoit] [autoit][/autoit] [autoit]

    Func OnAutoItExit()
    UDPCloseSocket($socket2)
    UDPShutdown()
    EndFunc

    [/autoit]

    Das Problem ist allerdings, das AutoIt immer ein anderen Destination-Port Source-Port über das UDP-Protokoll ausgibt.

    Hier mit der Orginalsoftware des Hersteller:
    [Blockierte Grafik: http://www.autoit.de/index.php?page=Attachment&amp;attachmentID=14922&amp;h=cf57d4673a1589d89195971bb3324b015f1ad7f8]

    Antwort vom Netzwerktelnehmer auf die Orginalsoftware des Hersteller:
    [Blockierte Grafik: http://www.autoit.de/index.php?page=Attachment&amp;attachmentID=14923&amp;h=fccb698a832fcc3805ca19d5d84c571947e4b32a]

    Hier mit meinem AutoIt Code:
    [Blockierte Grafik: http://www.autoit.de/index.php?page=Attachment&amp;attachmentID=14924&amp;h=615c244c30a01d3f14d6683b937e7e6d09cc0fb0]

    Antwort vom Netzwerktelnehmer auf den AutoIt Code:
    [Blockierte Grafik: http://www.autoit.de/index.php?page=Attachment&amp;attachmentID=14925&amp;h=e147424f89d246bfbe7a11faa6cbe0a5d2a879a1]

    Da AutoIt immer eine anderen Destination-Port Source-Port ausgibt, kann ich kein UDPBind erstellen, da ich nicht weiss auf welchen Port ich Empfangen muß! :cursing:

    Hat jemand von euch eine Idee, wie ich dieses Problem lösen kann?

    Vielen Dank schon mal für eure Hilfe!

    MfG
    Homer J. S.

  • Moin, solltest du nicht erst mal für dein Netz die BC Adresse ermitteln und dann an IP.255 deine Anfrage schicken der Switch leitet doch bei der BC Adresse sowieso alles in ein Boradcast um also sollte es doch genügen wenn du an die BC Adresse deinen HexString sendest und auf eine Antwort wartest oder?

    http://www.autoitscript.com/forum/topic/10…ess-with-tcpip/

    [autoit][/autoit][autoit][/autoit][autoit]

    MsgBox(0 ,"BC Adress" , GET_BROADCAST(@IPAddress1))

    [/autoit][autoit][/autoit][autoit]

    Func GET_BROADCAST($IP)
    $objWMIService = ObjGet("winmgmts:{impersonationLevel=Impersonate}!\\" & @ComputerName & "\root\cimv2")
    If Not IsObj($objWMIService) Then Exit
    $colAdapters = $objWMIService.ExecQuery ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
    For $objAdapter in $colAdapters
    If Not ($objAdapter.IPAddress) = " " Then
    For $i = 0 To UBound($objAdapter.IPAddress)-1
    If $objAdapter.IPAddress($i)=$IP Then Return BC_ADDR($objAdapter.IPAddress($i),$objAdapter.IPSubnet($i))
    Next
    EndIf
    Next
    Return 0
    EndFunc
    Func BC_ADDR($IP, $MASK)
    Local $BC=""
    $IP=StringSplit($IP , ".")
    $MASK=StringSplit($MASK , ".")
    If $IP[0]<>4 Then Return SetError(1,0,0)
    If $MASK[0]<>4 Then Return SetError(2,0,0)
    For $i=1 To 4
    $BC&=BitXOR(BitXOR($MASK[$i],255),BitAND($IP[$i],$MASK[$i]))&"."
    Next
    Return StringTrimRight($BC,1)
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    oder irre ich mich? :P

    [/autoit][autoit][/autoit][autoit]

    Gruß Marvin

    [/autoit]
  • Hi,

    also wenn ich das richtig verstanden habe, sendest du einen Broadcast an einen bestimmten Port ( 30718 ). Auf allen deinen Geräten, die auf diesen Broadcast antworten sollen, muss also ein Server-Programm laufen, welches auf den Port 30718 lauscht. Die Geräte, die auf deinen Broadcast antworten, senden ihre Antwort auf den von deinem Programm mitgegebenen Sourceport (63020). Du müsstest also nur mit UDPRecv diesen Port abhören.

  • @All
    Danke für eure Antworten!!
    In meinem ersten Post habe ich Source-Port mit Destination-Port vertauscht - Sorry!! -> Habe ich im ersten Post geändert.

    @Protex
    Das senden an 255.255.255.255:30718 funktioniert tadellos. Aber der Netzwerkteilnehmer antwortet ausschließlich auf den mitgegebenen Source-Port.
    Dieser ist leider nicht von AutoIt einstell oder auslesbar.

    @bastel123
    Einen UDPRecv würde ich ja gerne machen, aber ich weiß leider nicht was AutoIt für einen Source-Port an den Netwerkteilnehmer mitgibt, den dieser variiert.
    Der Port "63020" war nur ein Mittschnitt des Netzwerkes. Ein anderes mal kann er als Beispiel "63100" sein.

    Ich hoffe, ihr könnt mir dennoch weiter helfen?!

    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Hallo Zusammen,
    nach langem Suchen habe ich für mich die Lösung gefunden, die ich euch nicht vorenthalten möchte.

    Bei uns hier im Forum habe ich folgenden Beitrag bzw. Thema gefunden...:
    [ offen ] Bräuchte hilfe zu UDPOpen ( IPAddr, port )
    -> Mein besonderer Dank geht hier an "pretrojaner"

    ...dort wird eine Funktion Namens "_getDOSOutput" verwendet die man hier findet:
    [ gelöst ] Dos Abfrage nslookup %computername% auswerten

    Mit den Informationen habe ich einen kompakten Code erstellt, den ich auf Windows XP & 7 getestet habe:

    Bitte den Code von Post 8 verwenden, hier ist noch ein Bug vorhanden!!

    Spoiler anzeigen
    [autoit]

    ;Include Dateien
    #include <String.au3>
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    ;Declarationen
    $sourceport = '' ;Empfangsport
    $destinationport = 30718 ;Sendeport
    $ip_Local = @IPAddress1 ;Locale IP-Adresse (PC)
    $ip_Global = "255.255.255.255" ;Globale IP-Adresse (ganzes Netzwerk)

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP starten
    UDPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP-Socket erstellen zum senden
    $socket_tx = UDPOpen($ip_Global, $destinationport ,1)
    If @error <> 0 Then
    MsgBox(0, "Error UDPOpen", "Errornummer: " & @error)
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;Sourceport vom "UDPSend" lesen
    $UDPSend = UDPSend($socket_tx, '') ;Nachricht ohne Inhalt senden, um Sourceport im "netstat" zu erstellen
    Sleep(1000)
    $netstat = _getDOSOutput("netstat -aonp udp")
    $sourceport = StringReplace(StringMid($netstat, StringInStr($netstat, '*:*' & @AutoItPID)-5, 5), ':' , '')
    ;MsgBox(0, "Sourceport", $sourceport)

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP-Socket erstellen zum empfangen
    $socket_rx = UDPBind($ip_Local,$sourceport)
    If @error <> 0 Then
    MsgBox(0, "Error UDPBind", "Errornummer: " & @error)
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP-Nachricht senden & empfangen
    $UDPSend = UDPSend($socket_tx, _HexToString("000000F6"))
    While 1
    $data = ''
    $data = UDPRecv($socket_rx, 1024, 2)
    If $data<> '' Then
    _ArrayDisplay($data)
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ;Funktion: Console (DOS) senden/empfangen (unsichtbar)
    Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, '', @SW_HIDE, 2 + 4)
    While 1
    $text &= StdoutRead($Pid, False, False) & @CR
    If @error Then ExitLoop
    WEnd
    Return StringStripWS($text, 8) ;Modifiziert @ Homer J. S.
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;Funktion: Bei Codeende UPD-Funktionen schließen
    Func OnAutoItExit()
    UDPCloseSocket($socket_rx)
    UDPCloseSocket($socket_tx)
    UDPShutdown()
    EndFunc

    [/autoit]

    Mit diesem Code ist es möglich, eine UDP-Nachricht auf einen gewissen Port (Destinationport) zu senden und dann auf dem zufällig erstellten Port (Sourceport) zu empfangen.
    Es ist mit diesem Code nicht möglich , den Sourceport einzustellen! Dieser Code ist nur ein Beispiel und kann euch hoffentlich in euren Projekten unterstützen.

    Wenn einer eine elegantere Lösung oder eine Lösung mit einstellbaren Sourceport hat, dann bitte ich euch dieses hier zu posten.

    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

    Einmal editiert, zuletzt von Homer J. S. (15. Januar 2012 um 10:39)

  • peethebee

    Zitat

    Danke, dass du deine Lösung für alle bereitgestellt hast! :)

    ...gern gesehen! Das sollte aber doch selbstverständlich sein - oder?!


    @All
    Ich habe einen Bug gefunden. Wenn der zufällig erstellte "Sourceport" kleiner vierstellig (1-999) ist, dann gibt es einen inkorrekten "Sourceport" in meinem Code!

    Hier der gefixte Code:

    Spoiler anzeigen
    [autoit]

    ;Include Dateien
    #include <String.au3>
    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    ;Declarationen
    $sourceport = '' ;Empfangsport
    $destinationport = 30718 ;Zielport
    $ip_Local = @IPAddress1 ;Locale IP-Adresse (PC)
    $ip_Global = "255.255.255.255" ;Globale IP-Adresse (ganzes Netzwerk)

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP starten
    UDPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP-Socket erstellen zum senden
    $socket_tx = UDPOpen($ip_Global, $destinationport ,1)
    If @error <> 0 Then
    MsgBox(0, "Error UDPOpen", "Errornummer: " & @error)
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;Sourceport vom "UDPSend" lesen
    $UDPSend = UDPSend($socket_tx, '') ;Nachricht ohne Inhalt senden, um Sourceport im "netstat" zu erstellen
    Sleep(1000)
    $netstat = _getDOSOutput("netstat -aonp udp")
    $sourceport_array = StringSplit(StringMid($netstat, StringInStr($netstat, '*:*' & @AutoItPID)-5, 5), ':')
    $sourceport = $sourceport_array[$sourceport_array[0]]
    ;MsgBox(0, "Sourceport", $sourceport)

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP-Socket erstellen zum empfangen
    $socket_rx = UDPBind($ip_Local,$sourceport)
    If @error <> 0 Then
    MsgBox(0, "Error UDPBind", "Errornummer: " & @error)
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;UDP-Nachricht senden & empfangen
    $UDPSend = UDPSend($socket_tx, _HexToString("000000F6"))
    While 1
    $data = ''
    $data = UDPRecv($socket_rx, 1024, 2)
    If $data<> '' Then
    _ArrayDisplay($data)
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ;Funktion: Console (DOS) senden/empfangen (unsichtbar)
    Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, '', @SW_HIDE, 2 + 4)
    While 1
    $text &= StdoutRead($Pid, False, False) & @CR
    If @error Then ExitLoop
    WEnd
    Return StringStripWS($text, 8) ;Modifiziert @ Homer J. S.
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;Funktion: Bei Codeende UPD-Funktionen schließen
    Func OnAutoItExit()
    UDPCloseSocket($socket_rx)
    UDPCloseSocket($socket_tx)
    UDPShutdown()
    EndFunc

    [/autoit]

    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

    Einmal editiert, zuletzt von Homer J. S. (15. Januar 2012 um 10:45)

    • Offizieller Beitrag

    Ports mit Nummern von 1 bis 1023 sind unter UNIX traditionell den Administratoren vorbehalten und werden von der IANA (?) für einzelne Dienste "fest" vergeben. Das könnte hier zu Problemen führen, wenn du nicht mit #RequireAdmin entsprechende Rechte besorgst.
    Ich habe den Thread nicht im Detail nachvollzogen, muss also nicht unbedingt die Erklärung sein ;).

    Selbstverständlich ist ein Post mit der eigenen Lösung leider nicht :S.

    Johannes

  • peethebee

    Danke für den Tip mit dem...

    Zitat

    ...#RequireAdmin...

    ...werde ich im Hinterkopf behalten. Allerdings hat der "UDPSend" bisher nür fünfstellige "Sourceports" vergeben.

    Zitat

    Selbstverständlich ist ein Post mit der eigenen Lösung leider nicht :S.

    Es geht ja darum sich gegenseitig zu helfen und wenn man selber schneller ist, dann sollte man so fair sein, anderen User´n mit seiner Lösung auch zu helfen.
    Zumal ist das Forum nicht kommerziell wo jeder Anspruch hat direkt eine funktionierende Antwort zu erhalten. Daher bin ich sehr froh so ein kompetentes Forum überhaupt zu haben :thumbup:

    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Ist zwar schon länger her, hab aber hier eine Alternativlösung um den lokalen Port zu erhalten:

    Spoiler anzeigen
    [autoit]

    UDPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    Global $aSock = UDPOpen("255.255.255.255" , 17009, 1)
    UDPSend($aSock, "")

    [/autoit] [autoit][/autoit] [autoit]

    Global $iPortLocal = _Ws2_GetLocalPort($aSock[1])
    ConsoleWrite($iPortLocal & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Global $netstat = _getDOSOutput("netstat -aonp udp")
    Global $sourceport_array = StringSplit(StringMid($netstat, StringInStr($netstat, '*:*' & @AutoItPID)-5, 5), ':')
    Global $sourceport = $sourceport_array[$sourceport_array[0]]

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite($sourceport & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    UDPCloseSocket($aSock)
    UDPShutdown()

    [/autoit] [autoit][/autoit] [autoit]

    Func _Ws2_GetLocalPort($iSocket)
    ;funkey
    Local $hDLL = DllOpen("Ws2_32.dll")
    Local $tagIN_ADDR = "ulong S_addr;"
    Local $tagSOCKADDR_IN = "short sin_family;ushort sin_port;ptr sin_addr;char sin_zero[8];"
    Local $tIn_Addr = DllStructCreate($tagIN_ADDR)
    Local $tName = DllStructCreate($tagSOCKADDR_IN)
    DllStructSetData($tName, "sin_addr", DllStructGetPtr($tIn_Addr))

    [/autoit] [autoit][/autoit] [autoit]

    Local $aRes = DllCall($hDLL, "int", "getsockname", "uint", $iSocket, "struct*", $tName, "int*", 512)
    Local $aRes2 = DllCall($hDLL, "ushort", "ntohs", "ushort", DllStructGetData($tName, 2))

    [/autoit] [autoit][/autoit] [autoit]

    DllClose($hDLL)
    Return $aRes2[0]
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, '', @SW_HIDE, 2 + 4)
    While 1
    $text &= StdoutRead($Pid, False, False) & @CR
    If @error Then ExitLoop
    WEnd
    Return StringStripWS($text, 8) ;Modifiziert @ Homer J. S.
    EndFunc

    [/autoit]