Bräuchte hilfe zu UDPOpen ( IPAddr, port )

  • Hallo habe mal folgendes script geschrieben:

    Spoiler anzeigen
    [autoit]

    UDPStartup()
    $empfang = UDPBind("192.168.10.255", "xxxx") ; xxxx port adresse von der aus der Broadcast gesendet wurde
    If @error Then
    MsgBox(-1, "", "error startup")
    EndIf
    $socket = UDPOpen("192.168.10.255", 10011)
    If @error Then
    MsgBox(-1, "", "error udpopen")
    EndIf
    UDPSend($socket, "<query mess='1' id='test1'/>" & @CRLF)
    If @error Then
    MsgBox(-1, "", "error send")
    EndIf
    Sleep(3000)
    ;~ UDPSend($socket2, "<query mess='2' id='test1'/>"&@CRLF)
    ;~ if @error Then
    ;~ msgbox(-1,"","error send")
    ;~ endif
    MsgBox(0, "UDP Antwort", $empfang)
    UDPCloseSocket($socket)
    UDPShutdown()

    [/autoit]

    Im grunde funktioniert das ganze auch, der Connect findet statt und der String wird gesendet.

    Mein Problem hierbei ist jedoch, das die Verbindung jedes mal über einen anderen Port aufgebaut wird. Die Angabe für den Port bei

    UDPOpen ( IPAddr, port )

    bezieht sich ja nur auf den Zielport auf den Verbunden werden soll.

    Gibt es eine möglichkeit den Quellport vor zu definieren ?

    Der Grund warum ich das bräuchte: ich habe ein Device welches mir antwortet, aber nur auf dem Port von dem Ich aus sende.Dieser Port ist aber nach jedem erneuten Aufruf ein anderer. Habe dieses mit Wireshark und TCPview überprüft. Ich hoffe sehr ihr könnt mir weiter helfen.

  • Kann ja schon mal folgendes bei tragen. Ein UDF Broadcast auf "255.255.255.255" ist mit autoit bordmitteln nicht möglich (bug?) ein Broadcast jedoch auf "192.255.255.255" oder "192.168.255.255" oder auch auf "192.168.1.255" ist aber möglich.

    Jedoch ist es weiterhin so, das bei jedem ausgeführtem UDP Broadcast der gesendet wirt, offnet sich ein neuer und anderer local Port.

    Ich habe schon einmal folgendes Script hier im Forum gefunden mit dem schon mal der Broadcast auf alle Localen Netzwerkgeräte möglich ist d.H. auch auf "255.255.255.255". Hier das script:

    Spoiler anzeigen
    [autoit]

    UDPStartup()
    Global $WS = DllOpen("Ws2_32.dll")

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

    Global Const $AF_INET = 2
    Global Const $SOCK_DGRAM = 2

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

    Global Const $sockaddr_in = _
    "short family;" & _
    "ushort port;" & _
    "ulong addr;" & _
    "char zero[8];"

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

    Global Const $SOL_SOCKET = 0xFFFF
    Global Const $SO_BROADCAST = 0x20

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

    ; socket erstellen
    $SOCKET = DllCall($WS, "uint", "socket", "int", $AF_INET, "int", $SOCK_DGRAM, "int", 0)
    If Not @error Then $SOCKET = $SOCKET[0]

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

    ; broadcast erlauben
    DllCall($WS, "int", "setsockopt", "uint", $SOCKET, "int", $SOL_SOCKET, "int", $SO_BROADCAST, "int*", 1 , "int", 4)

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

    ; Ziel Adresse und Port
    $remote = DllStructCreate($sockaddr_in)
    DllStructSetData($remote, "family", $AF_INET)
    DllStructSetData($remote, "port", _htons(65532))
    DllStructSetData($remote, "addr", _inet_addr("255.255.255.255"))

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

    $to = DllStructGetPtr($remote)
    $toLen = DllStructGetSize($remote)

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

    ; Daten zum senden
    $Buffer = DllStructCreate("char[255]")
    DllStructSetData($Buffer,1,"hallo device melde dich")
    $pBuffer = DllStructGetPtr($Buffer)
    $BufLen = DllStructGetSize($Buffer)
    $Flags = 0

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

    ; senden
    $SENT = DllCall($WS, "int", "sendto", "uint", $SOCKET, "ptr", $pBuffer, "int", $BufLen, "int", $Flags, "ptr", $to, "int", $toLen)
    MsgBox(0, 'UDP broadcast', $SENT[0] & " Bytes gesendet")

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

    UDPShutdown()
    DllClose($WS)

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

    Func _htons($Short)
    ; Prog@ndy
    Local $aResult = DllCall($WS, "ushort", "htons", "ushort", $Short)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
    EndFunc
    Func _inet_addr($IP)
    ; Prog@ndy
    Local $aResult = DllCall($WS, "ulong", "inet_addr", "str", $IP)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
    EndFunc

    [/autoit]

    jedoch wird in diesem Script auch nur mit der Remote Port Adresse gearbeitet. Nun da ich mich mit den DLL Funktionen nicht auskenne, ist es für mich nicht möglich den entsprechenden localen Port mit einzufügen, von dem aus gesendet werden soll.

    denke aber das es möglich sein sollte genau dieses über diese ws2_32.dll zu bewerkstelligen.

    in dem nachfolgenden UDF Script wird z.b. das selbe gemacht wie mit TCPview (Microsoft). in diesem wird unter anderem der Interne Port abgefragt, ich denke mir mal alles was abgefragt werden kann müßte auch gesetzt werden können. Auch hier wird mit der ws2_32.dll gearbeitet. Ich hätte ja gerne selber mich drinne versucht, jedoch ist mir die Syntax für DLL einfach zu hoch. Man wird ja auch nicht jünger :rofl: .

    Spoiler anzeigen
    [autoit]

    ;~ _GetTCPtable( [optional handle to "ws2_32.dll" [, optional handle to "iphlpapi.dll" ] ] )
    ;~
    ;~ Return Value
    ;~ Success: TCPtable[][] = 2-D array
    ;~ [0][0] = number of connections
    ;~ for connection n:
    ;~ [n][0] = connection state (integer)
    ;~ [n][1] = local IP
    ;~ [n][2] = local port
    ;~ [n][3] = remote IP
    ;~ [n][4] = remote port
    ;~ [n][5] = connection state (informative text)
    ;~ Failure: TCPtable[0][0] = -1

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

    Func _GetTCPtable($WSdll = "ws2_32.dll", $IHdll = "iphlpapi.dll")

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

    Local Const $connState[12] = ["CLOSED", "LISTENING", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "FIN_WAIT1", _
    "FIN_WAIT2", "CLOSE_WAIT", "CLOSING", "LAST_ACK", "TIME_WAIT", "DELETE_TCB"]

    Local $TCPtable[1][1] = [[ -1]] ; preset to "failed"
    $dwSize = DllStructCreate("dword") ; for MIB_TCPTABLE buffer size

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

    $MIB_TCPTABLE = DllStructCreate("dword") ; nominal struct initially
    DllStructSetData($dwSize, 1, 0) ; force zero size
    $ret = DllCall($IHdll, "int", "GetTcpTable", "ptr", DllStructGetPtr($MIB_TCPTABLE), "ptr", DllStructGetPtr($dwSize), "int", 1) ; get size
    If @error Or $ret[0] <> 122 Then Return $TCPtable ; dllCall error or RC is *not* ERROR_INSUFFICIENT_BUFFER = 122

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

    $MIB_TCPTABLE = ""
    For $i = 1 To DllStructGetData($dwSize, 1) / 4 ; make to requested size of buffer
    $MIB_TCPTABLE &= "dword;"
    Next
    $MIB_TCPTABLE = DllStructCreate(StringTrimRight($MIB_TCPTABLE, 1)) ; requested struct
    DllStructSetData($dwSize, 1, DllStructGetSize($MIB_TCPTABLE)) ; recheck its size
    $ret = DllCall($IHdll, "int", "GetTcpTable", "ptr", DllStructGetPtr($MIB_TCPTABLE), "ptr", DllStructGetPtr($dwSize), "int", 1) ; get data
    If @error Or $ret[0] Then Return $TCPtable ; dllCall error or RC is Error

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

    $numTCPentries = DllStructGetData($MIB_TCPTABLE, 1) ; number of entries
    ReDim $TCPtable[$numTCPentries + 1][6]

    For $i = 1 To $numTCPentries
    $offset = ($i - 1) * 5 + 1 ; dword offset into struct
    $TCPtable[$i][0] = DllStructGetData($MIB_TCPTABLE, $offset + 1) ; integer connection state
    $TCPtable[$i][5] = $connState[$TCPtable[$i][0] - 1] ; connection state text

    $ret = DllCall($WSdll, "str", "inet_ntoa", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 2)) ; local IP / translate
    If @error Then Return $TCPtable ; dllCall error
    $TCPtable[$i][1] = $ret[0]
    $ret = DllCall($WSdll, "ushort", "ntohs", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 3)) ; local port / translate
    _ArrayDisplay($ret)
    If @error Then Return $TCPtable ; dllCall error
    $TCPtable[$i][2] = $ret[0]

    If $TCPtable[$i][0] <= 2 Then ; CLOSED or LISTENING state
    $TCPtable[$i][3] = "0.0.0.0"
    $TCPtable[$i][4] = 0
    Else
    $ret = DllCall($WSdll, "str", "inet_ntoa", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 4)) ; remote IP / translate
    If @error Then Return $TCPtable ; dllCall error
    $TCPtable[$i][3] = $ret[0]
    $ret = DllCall($WSdll, "ushort", "ntohs", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 5)) ; remote port / translate
    If @error Then Return $TCPtable ; dllCall error
    $TCPtable[$i][4] = $ret[0]
    EndIf
    Next

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

    $dwSize = 0
    $MIB_TCPTABLE = 0
    $TCPtable[0][0] = $numTCPentries ; success
    Return $TCPtable

    EndFunc ;==>_GetTCPtable

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

    ;~ _CloseTCPconnection( LocalIP, LocalPort, RemoteIP, RemotePort, [optional handle to "ws2_32.dll" [, optional handle to "iphlpapi.dll"]] )
    ;~
    ;~ Return Value
    ;~ Success: 1
    ;~ Failure: 0

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

    Func _CloseTCPconnection($localIP, $localPort, $remoteIP, $remotePort, $WSdll = "ws2_32.dll", $IHdll = "iphlpapi.dll")

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

    $MIB_TCPROW = DllStructCreate("dword;dword;dword;dword;dword") ; connection struct
    DllStructSetData($MIB_TCPROW, 1, 12) ; set to DELETE_TCB state = 12

    $ret = DllCall($WSdll, "uint", "inet_addr", "str", $localIP) ; local IP / translate
    If Not @error Then DllStructSetData($MIB_TCPROW, 2, $ret[0])
    $ret = DllCall($WSdll, "uint", "htons", "ushort", $localPort) ; local port / translate
    If Not @error Then DllStructSetData($MIB_TCPROW, 3, $ret[0])

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

    $ret = DllCall($WSdll, "uint", "inet_addr", "str", $remoteIP) ; remote IP / translate
    If Not @error Then DllStructSetData($MIB_TCPROW, 4, $ret[0])
    $ret = DllCall($WSdll, "uint", "htons", "ushort", $remotePort) ; remote port / translate
    If Not @error Then DllStructSetData($MIB_TCPROW, 5, $ret[0])

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

    $ret = DllCall($IHdll, "int", "SetTcpEntry", "ptr", DllStructGetPtr($MIB_TCPROW)) ; close connection
    If @error Or $ret[0] Then Return 0 ; dllCall error or RC is Error

    $MIB_TCPROW = 0
    Return 1 ; success

    EndFunc ;==>_CloseTCPconnection

    [/autoit]

    vieleicht findet sich ja ein pfiffiger der dieses lösen kann.

    Gruß

  • So habe im Grunde die Lösung meines Problemes selber gefunden und gelöst. Jedoch möchte ich dieses natürlich auch weitergeben.

    Folgendes Script habe ich unter Win7 Programiert:

    Spoiler anzeigen
    [autoit]

    #include <Constants.au3>
    #include <Array.au3>
    #include <String.au3>
    #include <file.au3>
    UDPStartup()
    #Region Broadcast IP erstellen und Port öffnen zu dem gesendet werden soll.
    $My_ips = StringSplit(@IPAddress1, '.')
    $Broadcast = $My_ips[1] & '.' & $My_ips[2] & '.' & $My_ips[3] & '.255'
    $socket = UDPOpen($Broadcast, 10011)
    If @error Then
    MsgBox(-1, "", "error udpopen")
    Exit
    EndIf
    #EndRegion Broadcast IP erstellen und Port öffnen zu dem gesendet werden soll.
    sendepunkt() ; irgentetwas senden um einen Port zu aktivieren
    #Region Port auslesen von dem aus gesendet wurde
    $ausgabe = _getDOSOutput("netstat -aonp udp")
    $ausgabe = StringStripWS($ausgabe, 8)
    $ausgabe = StringTrimRight($ausgabe, StringLen($ausgabe) - StringInStr($ausgabe, "*:*" & @AutoItPID) - 6)
    $ausgabe = StringTrimLeft($ausgabe, StringInStr($ausgabe, "*:*" & @AutoItPID) - 25)
    $zwischenwert = _StringBetween($ausgabe, "0.0.0.0:", "*:*" & @AutoItPID)
    $port = _ArrayUnique($zwischenwert)
    #EndRegion Port auslesen von dem aus gesendet wurde
    #Region Auf ausgelesenem Port horchen und Qustion senden, anschließend die Antwort in eine log datei schreiben
    $socket1 = UDPBind(@IPAddress1, $port[1])
    If @error <> 0 Then Exit
    If FileExists(@ScriptDir & "\logfile.log") Then FileDelete(@ScriptDir & "\logfile.log")
    While 1
    For $i = 1 To 3
    UDPSend($socket, "<query mess='" & $i & "' id='test1'/>." & @CRLF)
    Next
    $data = UDPRecv($socket1, 1024)
    If $data <> "" Then
    $file = FileOpen(@ScriptDir & "\logfile.log", 1)
    If $file = -1 Then
    MsgBox(0, "Error", "Unable to open logfile.")
    Exit
    EndIf
    FileWrite($file, $data)
    FileWrite($file, @CRLF)
    FileClose($file)
    Sleep(500)
    ExitLoop
    Else
    MsgBox(0, "Fehler", "Keine Geräte Online oder verbunden")
    Exit 0
    EndIf
    Sleep(100)
    WEnd
    #EndRegion Auf ausgelesenem Port horchen und Qustion senden, anschließend die Antwort in eine log datei schreiben

    [/autoit]

    Dieses funktioniert unter Win7 ohne Probleme.

    Jedoch unter Windows XP gibt es in der Zeile: 25 ein Problem

    diese zeile gibt einen fehler zurück.

    $socket1 = UDPBind(@IPAddress1, $port[1])

    Kann mir jemand helfen ? wie gesagt unter WIN7 funktioniert dieses. ohne fehler.

  • welchen Fehler bekommst Du denn zurück?

    MfG Schnuffel

    "Sarkasmus ist die niedrigste Form des Witzes, aber die höchste Form der Intelligenz."
    Val McDermid

    ein paar Infos ...

    Wer mehr als "nur" Hilfe benötigt, kann sich gern im Forum "Programmieranfragen" an uns wenden. Wir helfen in allen Fällen, die die Forenregeln zulassen.

    Für schnelle Hilfe benötigen wir ein ! lauffähiges ! Script, dass wir als Demonstration des Problems testen können. Wer von uns erwartet ein Teilscript erstmal lauffähig zu bekommen, der hat
    1. keine wirkliche Not
    2. keinen Respekt vor Menschen die ihm in ihrer Freizeit Ihre Hilfe anbieten
    3. oder ist einfach nur faul und meint wir coden das für ihn

    In solchen Fällen erlaube ich mir, die Anfrage einfach zu ignorieren. ;)

  • Reine Spekulation aber vllt. so?

    Spoiler anzeigen
    [autoit]

    #include <Constants.au3>
    #include <Array.au3>
    #include <String.au3>
    #include <file.au3>
    UDPStartup()
    #Region Broadcast IP erstellen und Port öffnen zu dem gesendet werden soll.
    $My_ips = StringSplit(@IPAddress1, '.')
    $Broadcast = $My_ips[1] & '.' & $My_ips[2] & '.' & $My_ips[3] & '.255'
    $socket = UDPOpen($Broadcast, 10011)
    If @error Then
    MsgBox(-1, "", "error udpopen")
    Exit
    EndIf
    #EndRegion Broadcast IP erstellen und Port öffnen zu dem gesendet werden soll.
    sendepunkt() ; irgentetwas senden um einen Port zu aktivieren
    #Region Port auslesen von dem aus gesendet wurde
    $ausgabe = _getDOSOutput("netstat -aonp udp")
    $ausgabe = StringStripWS($ausgabe, 8)
    $ausgabe = StringTrimRight($ausgabe, StringLen($ausgabe) - StringInStr($ausgabe, "*:*" & @AutoItPID) - 6)
    $ausgabe = StringTrimLeft($ausgabe, StringInStr($ausgabe, "*:*" & @AutoItPID) - 25)
    $zwischenwert = _StringBetween($ausgabe, "0.0.0.0:", "*:*" & @AutoItPID)
    $port = _ArrayUnique($zwischenwert)
    #EndRegion Port auslesen von dem aus gesendet wurde
    #Region Auf ausgelesenem Port horchen und Qustion senden, anschließend die Antwort in eine log datei schreiben
    If @error <> 0 Then Exit
    If FileExists(@ScriptDir & "\logfile.log") Then FileDelete(@ScriptDir & "\logfile.log")
    While 1
    For $i = 1 To 3
    UDPSend($socket, "<query mess='" & $i & "' id='test1'/>." & @CRLF)
    Next
    UDPCloseSocket($socket)
    $socket1 = UDPBind(@IPAddress1, $port[1])
    $data = UDPRecv($socket1, 1024)
    If $data <> "" Then
    $file = FileOpen(@ScriptDir & "\logfile.log", 1)
    If $file = -1 Then
    MsgBox(0, "Error", "Unable to open logfile.")
    Exit
    EndIf
    FileWrite($file, $data)
    FileWrite($file, @CRLF)
    FileClose($file)
    Sleep(500)
    ExitLoop
    Else
    MsgBox(0, "Fehler", "Keine Geräte Online oder verbunden")
    Exit 0
    EndIf
    Sleep(100)
    WEnd
    #EndRegion Auf ausgelesenem Port horchen und Qustion senden, anschließend die Antwort in eine log datei schreiben

    [/autoit]
  • Ich danke dir vielmals, obwohl ich es noch nicht ganz verstehe warum, und die logik ich dahinter nicht verstehe Funktioniert es. Tausend dank :rock: :rock: :rock: :rock: :D :D

  • ich denke mal du hattest mit Deiner "Ahnung" 10048 schon Recht.
    Laut Google geht es eben nicht, gleichzeitig an einem Port zu senden und zu hören...
    Daher hat blubbstar den Port vor den lauschen geschlossen...

    Spoiler anzeigen
    [autoit]

    UDPCloseSocket($socket)
    $socket1 = UDPBind(@IPAddress1, $port[1])

    [/autoit]

    MfG Schnuffel

    "Sarkasmus ist die niedrigste Form des Witzes, aber die höchste Form der Intelligenz."
    Val McDermid

    ein paar Infos ...

    Wer mehr als "nur" Hilfe benötigt, kann sich gern im Forum "Programmieranfragen" an uns wenden. Wir helfen in allen Fällen, die die Forenregeln zulassen.

    Für schnelle Hilfe benötigen wir ein ! lauffähiges ! Script, dass wir als Demonstration des Problems testen können. Wer von uns erwartet ein Teilscript erstmal lauffähig zu bekommen, der hat
    1. keine wirkliche Not
    2. keinen Respekt vor Menschen die ihm in ihrer Freizeit Ihre Hilfe anbieten
    3. oder ist einfach nur faul und meint wir coden das für ihn

    In solchen Fällen erlaube ich mir, die Anfrage einfach zu ignorieren. ;)