![]() |
AW: Re: Eigene IP Adresse ermitteln
Auf den Zug will/muss ich mal aufspringen:
Zitat:
Ich brauche genau den Adaptor, mit dem ich im lokalen Netz verbunden bin. Folgende Funktion liefert mir zwar mehrere IP. Dass die letzte nicht immer die passende sein muss, ist mir dabei klar. Aber wie löse ich dieses Zuordnungsproblem?
Delphi-Quellcode:
Ich habe übrigens 3 IP-Adressen: 1x LAN, 1x WLAN, 1x VirtualBox-Adapter. Das Problem dabei ist, dass ich an 2 Laptops mit gleicher Konfiguration unterschiedliche Ergebnisse bekomme. Ich vermute, dass es allein an der Installationsreihenfolge der Treiber liegt.
Function GetLocalIP: String;
Type TaPInAddr = Array [0..10] Of PInAddr; PaPInAddr =^TaPInAddr; Var Buffer : PAnsiChar; aWSAData : TWSAData; aHostEnt : PHostEnt; pptr : PaPInAddr; I : Integer; Begin Result:= ''; Buffer:= Addr(Result[1]); If (WSAStartup($0101, aWSAData) = 0) Then Try If (GetHostName(buffer, MAX_PATH) <> 0) Then Begin aHostEnt:= GetHostByName(buffer); If (aHostEnt <> nil) Then Begin pPtr:= PaPInAddr(aHostEnt^.h_addr_list); I:= 0; While (pPtr^[I] <> nil) Do Begin Result:= String(inet_ntoa(pptr^[I]^)); Inc(I); End; End; End; Finally WSACleanup; End; End; P.S. Ich finde übrigens diese überall zu findende Funktion nicht so furchtbar, dass man sich nach Java flüchten müsste. |
AW: Eigene IP Adresse ermitteln
Das Problem an deine Aufgabe ist, dass es nicht den Adapter mit der IP gibt.
Ein Adapter kann problemlos mehrere IPs haben. Und du kannst über mehrere Adapter auch mit mehreren Netzen verbunden sein. Du solltest immer davon ausgehen, dass sowas vorkommen kann. Bring deinem Programm bei, mit allen Umständen umgehen zu können. Es wäre unheimlich ärgerlich, wenn dein Programm nicht benutzbar wäre, weil du dachtes, es sei einfacher für den Benutzer, wenn er keinerlei Auswahlmöglichkeit hat. Ansonsten, für einen "Einfachen Modus" oder als Standardauswahl: Nimm den Adapter mit dem Netz, der zuständig für die Standardroute (0.0.0.0 mit Maske 0.0.0.0) ist:
Code:
Obacht: es kann auch mehrere Standardrouten geben. Nimm die mit höchster Priorität (kleinster Metrik).
C:\Users\Valentin>route PRINT -4
[...] IPv4-Routentabelle =========================================================================== Aktive Routen: Netzwerkziel Netzwerkmaske Gateway Schnittstelle Metrik 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.50 10 <-- Standardroute mit Gateway- und Adapter-IP 127.0.0.0 255.0.0.0 Auf Verbindung 127.0.0.1 306 127.0.0.1 255.255.255.255 Auf Verbindung 127.0.0.1 306 127.255.255.255 255.255.255.255 Auf Verbindung 127.0.0.1 306 169.254.0.0 255.255.0.0 Auf Verbindung 169.254.168.57 266 169.254.168.57 255.255.255.255 Auf Verbindung 169.254.168.57 266 169.254.255.255 255.255.255.255 Auf Verbindung 169.254.168.57 266 192.168.1.0 255.255.255.0 Auf Verbindung 192.168.1.50 266 192.168.1.50 255.255.255.255 Auf Verbindung 192.168.1.50 266 192.168.1.255 255.255.255.255 Auf Verbindung 192.168.1.50 266 224.0.0.0 240.0.0.0 Auf Verbindung 127.0.0.1 306 224.0.0.0 240.0.0.0 Auf Verbindung 169.254.168.57 266 224.0.0.0 240.0.0.0 Auf Verbindung 192.168.1.50 266 255.255.255.255 255.255.255.255 Auf Verbindung 127.0.0.1 306 255.255.255.255 255.255.255.255 Auf Verbindung 169.254.168.57 266 255.255.255.255 255.255.255.255 Auf Verbindung 192.168.1.50 266 =========================================================================== Ständige Routen: Keine |
AW: Eigene IP Adresse ermitteln
Was ist mit so was:
![]() Hab so was vor Jahren auch mal gebraucht und dort öffentlich gestellt... Jan |
AW: Eigene IP Adresse ermitteln
Zitat:
Nach welchen Befehlen kann ich das mit Delphi realisieren? Wonach muss ich suchen? Ich wollte das ungern über einen Shell-Aufruf mit anschließendem Einlesen und Auswerten einer externen Datei. Zitat:
Delphi-Quellcode:
auf den ersten Blick dort nicht zu geben...
tNetworkInterface
Danke soweit erstmal für Eure tollen Antworten! |
AW: Eigene IP Adresse ermitteln
Zitat:
In Delphi XE5 hagelt es aber Hinweise bzgl. PChar und PAnsiChar sowie zu impliziten String-Umwandlungen. Ein paar schönheitsfehler im Code und am Ende dann aber der Punkt, dass die Funktion immer True zurückgibt. Gibt es dafür einen Grund? Und am Ende werden von 5 Adaptern auch nur 2 gefunden, wobei der mit der richtigen IP fehlt. Die von mir eingangs gepostete Funktion liefert das gebrauchte ja auch schon zurück. Ich muss also bloß herausfinden, was die höchste Metric hat, wie man das programmtechnisch mit Delphi umsetzt und dann wäre ich fertig. |
AW: Eigene IP Adresse ermitteln
Ihr verwechselt hier etwas. Die Funktion von BoolString interiert nur die Adapter. Dort gibt es keine Standardgateways und auch keine Metriken.
Du musst die IPv4 Routingtabelle iterieren. Wie du schon sagst, ist es natürlich besser, das nicht per CLI zu machen! :thumb: Ich habe keine Ahnung wie du das mit Delphi machst. Ich denke aber, dass WMI ein Ansatz ist. Google hat mir ![]() |
AW: Eigene IP Adresse ermitteln
Auch das werde ich mir ansehen. Vielleicht hat sich ja schon jemand die Mühe gemacht, das in Delphi umzusetzen. Ich selbst bin bloß Laie und kenne meine Grenzen ganz gut :lol:
Allerdings bin ich ein Stück weiter: Bei meiner teils diffusen Suche bin ich immerhin auf z.B. ![]() ![]() So ist jedenfalls mein aktueller Ansatz. Das mit der Metric sehe ich mir aber trotzdem an. Denn es kann auch 2 aktive Adapter geben, wenn man z.B. als Rechner 2 Subnetzen - einmal per LAN, einmal per WLAN oder gar per VPN - angehört. Ich hätte schon gern ein berechnebares Ergebnis der Funktion. |
AW: Eigene IP Adresse ermitteln
Also der Code von
Zitat:
Hier mal eine Variante, die die Indy-Winsock2-Implementierung verwendet und gleichzeigt auch aussagekräftige Fehlermeldungen herauswirft (wenn denn welche auftreten). Man könnte jetzt noch ein wenig spezieller auf bestimmte Fehler reagieren (z.B. wenn der Buffer zu klein ist) aber das spare ich mir jetzt mal ;)
Delphi-Quellcode:
Dazu gehört dann noch
unit Winapi.NetworkInterfaces;
interface uses IdWinsock2; type tNetworkInterface = record AddrIP: string; SubnetMask: string; AddrNet: string; AddrLimitedBroadcast: string; AddrDirectedBroadcast: string; IsInterfaceUp: Boolean; BroadcastSupport: Boolean; IsLoopback: Boolean; IsPointToPoint: Boolean; IsMulticast: Boolean; end; tNetworkInterfaceList = array of tNetworkInterface; function GetNetworkInterfaces( ): tNetworkInterfaceList; implementation uses Winapi.Errors; procedure RaiseLastWinsocket2Error( const AdditionalInfo: string = '' ); begin RaiseLastModuleError( WinsockHandle( ), WSAGetLastError( ), AdditionalInfo ); end; function GetNetworkInterfaces( ): tNetworkInterfaceList; var aSocket : TSocket; NoOfInterfaces : Integer; NoOfBytesReturned : u_Long; InterfaceFlags : u_Long; pAddrIP : sockaddr_in; pAddrSubnetMask : sockaddr_in; pAddrBroadcast : sockaddr_in; pIPString : PAnsiChar; pSubnetMaskString : PAnsiChar; pLimBroadcastString: PAnsiChar; pNetAddrString : PAnsiChar; pDirBroadcastString: PAnsiChar; DirBroadcastDummy : In_Addr; NetAddrDummy : In_Addr; Buffer : array [ 0 .. 30 ] of interface_info; cbOutBuffer : u_Long; i : Integer; begin InitializeWinSock; SetLength( Result, 0 ); aSocket := Socket( AF_INET, SOCK_STREAM, 0 ); if ( aSocket = INVALID_SOCKET ) then RaiseLastWinsocket2Error( ); try cbOutBuffer := Length( Buffer ) * SizeOf( interface_info ); if WSAIoctl( aSocket, SIO_GET_INTERFACE_LIST, nil, 0, @Buffer, cbOutBuffer, @NoOfBytesReturned, nil, nil ) <> 0 then RaiseLastWinsocket2Error( ); NoOfInterfaces := NoOfBytesReturned div SizeOf( interface_info ); SetLength( Result, NoOfInterfaces ); // For each of the identified interfaces get: for i := 0 to NoOfInterfaces - 1 do begin with Result[ i ] do begin // Get the IP address pAddrIP := Buffer[ i ].iiAddress.AddressIn; pIPString := inet_ntoa( pAddrIP.sin_addr ); AddrIP := string( pIPString ); // Get the subnet mask pAddrSubnetMask := Buffer[ i ].iiNetmask.AddressIn; pSubnetMaskString := inet_ntoa( pAddrSubnetMask.sin_addr ); SubnetMask := string( pSubnetMaskString ); // Get the limited broadcast address pAddrBroadcast := Buffer[ i ].iiBroadcastAddress.AddressIn; pLimBroadcastString := inet_ntoa( pAddrBroadcast.sin_addr ); AddrLimitedBroadcast := string( pLimBroadcastString ); // Calculate the net and the directed broadcast address NetAddrDummy.S_addr := Buffer[ i ].iiAddress.AddressIn.sin_addr.S_addr; NetAddrDummy.S_addr := NetAddrDummy.S_addr and Buffer[ i ].iiNetmask.AddressIn.sin_addr.S_addr; DirBroadcastDummy.S_addr := NetAddrDummy.S_addr or not Buffer[ i ].iiNetmask.AddressIn.sin_addr.S_addr; pNetAddrString := inet_ntoa( ( NetAddrDummy ) ); AddrNet := string( pNetAddrString ); pDirBroadcastString := inet_ntoa( ( DirBroadcastDummy ) ); AddrDirectedBroadcast := string( pDirBroadcastString ); // From the evaluation of the Flags we receive more information InterfaceFlags := Buffer[ i ].iiFlags; IsInterfaceUp := ( InterfaceFlags and IFF_UP ) = IFF_UP; BroadcastSupport := ( InterfaceFlags and IFF_BROADCAST ) = IFF_BROADCAST; IsLoopback := ( InterfaceFlags and IFF_LOOPBACK ) = IFF_LOOPBACK; IsPointToPoint := ( InterfaceFlags and IFF_POINTTOPOINT ) = IFF_POINTTOPOINT; IsMulticast := ( InterfaceFlags and IFF_MULTICAST ) = IFF_MULTICAST; end; end; finally CheckModuleError( CloseSocket( aSocket ), WinsockHandle( ) ); end; end; initialization finalization UninitializeWinSock; end.
Delphi-Quellcode:
unit Winapi.Errors;
interface uses System.SysUtils, Winapi.Windows; procedure CheckModuleError( LastError: Integer; AModuleName: string; const AdditionalInfo: string = '' ); overload; procedure CheckModuleError( LastError: Integer; AModuleHandle: HMODULE; const AdditionalInfo: string = '' ); overload; procedure RaiseLastModuleError( AModuleName: string; LastError: Integer; const AdditionalInfo: string = '' ); overload; procedure RaiseLastModuleError( AModuleHandle: HMODULE; LastError: Integer; const AdditionalInfo: string = '' ); overload; implementation uses System.SysConst; procedure CheckModuleError( LastError: Integer; AModuleName: string; const AdditionalInfo: string = '' ); begin if LastError <> ERROR_SUCCESS then RaiseLastModuleError( AModuleName, LastError, AdditionalInfo ); end; procedure CheckModuleError( LastError: Integer; AModuleHandle: HMODULE; const AdditionalInfo: string = '' ); begin if LastError <> ERROR_SUCCESS then RaiseLastModuleError( AModuleHandle, LastError, AdditionalInfo ); end; procedure RaiseLastModuleError( AModuleName: string; LastError: Integer; const AdditionalInfo: string = '' ); begin UniqueString( AModuleName ); RaiseLastModuleError( LoadLibrary( PChar( AModuleName ) ), LastError, AdditionalInfo ); end; procedure RaiseLastModuleError( AModuleHandle: HMODULE; LastError: Integer; const AdditionalInfo: string = '' ); var Error: EOSError; begin if LastError <> 0 then Error := EOSError.CreateResFmt( @SOSError, [ LastError, SysErrorMessage( LastError, AModuleHandle ), AdditionalInfo ] ) else Error := EOSError.CreateRes( @SUnkOSError ); Error.ErrorCode := LastError; raise Error; end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz