Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Eigene IP Adresse ermitteln (https://www.delphipraxis.net/144872-eigene-ip-adresse-ermitteln.html)

Cicaro 18. Dez 2009 13:32


Eigene IP Adresse ermitteln
 
Hallo.

Ich dachte so etwas sollte eigentlich leicht in einem Forum zu finden sein, aber ich habe nichts gescheites gefunden.

Einfache Aufgabe: IP Adresse in der eigenen Delphi Anwendung ermitteln. Ob Array von 4 Zahlen oder String ist egal. Möglichst kurz und einfach sollte es sein, damit man es verstehen kann.

a) Generel: Wie kommt man an die eigene IP in einer Konsolen-Anwendung.
b) Sockets: Also ich arbeite eigentlich mit TClientSocket/TServerSocket, die nicht auf der Form liegen. Wie kann man die IP mit Hilfe der Delphi Unit "ScktComp" ermitteln ?
c) Welche anderen Formen gibt es die IP zu ermitteln (z.B. Indy etc.)?

Folgendes bietet Java kurz und knackig an:
Delphi-Quellcode:
String[] strings = InetAddress.getLocalHost().toString().split("/");
String myIP = strings[strings.length - 1];
Warum auch nicht Delphi in vergleichbarer Form ?

Das hier hab ich schon gesehen. Bitte nicht so etwas anbieten.

MfG

rollstuhlfahrer 18. Dez 2009 14:15

Re: Eigene IP Adresse ermitteln
 
HI,

kommt ganz darauf an, welche IP du haben willst. Die öffentliche IP (Internet) oder die private Adresse (lokales Netz). Die erstere bekommst du bei Seitenaufrufen auf Seiten, die dir deine IP verraten, letztere durch einen API-Aufruf.
Für letztere hast du ja schon einen Weg gefunden. Ich kann dir nur einen sehr ähnlichen oder fast den selben anbieten.

Die Seiten für die öffentliche IP bekommst du hier: http://www.delphipraxis.net/internal...=252395#252395 . Du kannst aber auch selbst ne Seite bauen, um dem Datenschutz besser folge zu leisten.

Bernhard

EDIT: Die angegebenen Links führten größtenteils zu 404-Seiten, also mal schnell:

Aphton 18. Dez 2009 14:44

Re: Eigene IP Adresse ermitteln
 
Ich geh mal davon aus, es ist die Rede von der globalen IP Adresse, denn für die lokale gibts hier genug Sourcen.

Versuch mal whatismyipaddress.com in cmd anzupingen.
Falls das funktioniert, schreibe dir die IP dieser Seite auf und mache folgendes:
1. telnet <ip> 80
2. Nach Verbindungsaufbau folgendes tippen:
Code:
GET / HTTP/1.1<enter>
Host: <IrgendEineIP><enter>
<enter>
<enter>
Genau diesen Vorgang kannst du auch "automatisieren" / "programmieren".
Folgender Code dürfte solch eine Verbindung aufbauen, denn HTTP Request senden, Rückgabe-String parsen und dir deine globale IP Adresse als String zurückgeben.

Delphi-Quellcode:
uses WinSock2;

function GetWANIP(): String;
// whatismyipaddress.com -- 140.239.191.10
var
  WSAD: TWSAData;
  Sock: TSocket;
  Addr: TSockAddrIn;
  Timo: Cardinal;
  GetMsg: String;
  Buffer: Array[0..$400-1] of Char;
begin
  if WSAStartup( $202, WSAD ) = 0 then
  begin
    Sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
    if Sock <> SOCKET_ERROR then
    begin
      Timo := $1000;
      setsockopt( Sock, SOL_SOCKET, SO_SNDTIMEO, pChar( @Timo ), SizeOf( Timo ) );
      with Addr do
      begin
        sin_family := AF_INET;
        sin_port := htons( 80 );
        sin_addr.S_addr := inet_addr( '140.239.191.10' );
      end;
      if connect( Sock, @Addr, SizeOf( Addr ) ) = 0 then
      begin
        GetMsg := 'GET / HTTP/1.1'#13#10+
                  'Host: 140.239.191.10'#13#10#13#10;
        Timo := Length( GetMsg );
        if send( Sock, GetMsg[1], Timo, 0 ) = Timo then
        begin
          FillChar( Buffer[0], $400, 0 );
          if recv( Sock, Buffer[0], $400, 0 ) > 0 then
          begin
            Result := Buffer;
            Timo := Pos( #13#10#13#10, Result );
            if Timo > 0 then
              Result := Copy( Result, Timo+4, 15 );
          end;
        end;
      end;
      closesocket( Sock );
    end;
    WSACleanup();
  end;
end;
MfG

Astat 18. Dez 2009 15:15

Re: Eigene IP Adresse ermitteln
 
Hallo Cicaro.

Zitat:

Zitat von Cicaro
Möglichst kurz und einfach sollte es sein, damit man es verstehen kann.

Windows arbeitet mit Adaptoren, dh. Pro Netzwerkkarte gibt es einen Netzwerkadapter.
Es gibt Hardware und Software Adaptoren (virtuelle Adaptoren).
Virtuelle Adaptoren können mittels API in fast beliebiger Anzahl erstellt werden.
Jeder Adapter erhält eine MAC-Adresse und IP.
Also wenn Du die IP ermitteln möchtest, musst du wissen von welchem Adapter du diese auslesen willst.

Beispiel Notebook:
W-Lan, NIC, ISDN, ADSL, Firewalls, Virenscanner, BlueTooth usw.
Hier kann es möglich sein, dass bis zu 7 IP's (Adaptoren) vorhanden sind.

Also Kurz und einfach, ohne sich genauer mit der Materie zu beschäftigen, wirds nicht gehen!

Wenn Du Komponenten wie "ScktComp" verwendest, wird immer die IP des an den Adapter gebundenen Sockets ausgegeben.

Bei Verwendung von "komplizierter" Socket-API oder IPHelper-API ist es jederzeit möglich alle IP's korrekt zu ermitteln!

Oder man verwendet die "kurz und knackige Java Funktion", und weiss anschliessend nicht was man eigentlich getan hat!

Zitat:

Zitat von Cicaro
Wie kommt man an die eigene IP in einer Konsolen-Anwendung.

Mit den genannten API's!

http://msdn.microsoft.com/en-us/library/aa366073(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms740506(VS.85).aspx

lg. Astat

sirius 18. Dez 2009 15:36

Re: Eigene IP Adresse ermitteln
 
a) Man nutzt die gleichen Möglichkeiten, wie in einer Formularanwendung. --> Frage ist obsolet
b) In dieser Unit gibt es dafür keine Funktionen oder Methoden
c) Mit Indy erstellst du dir ein Objekt von TidIPWatch und suchst dir die passende Methode.
d) Weitere Möglichkeiten wurden genannt oder finden sich u.a hier in der CodeLib

Edit:
Hier sind zwei Lösungen. Aber sie geben nur eine der möglichen IP'n wieder (siehe Astat).
Delphi-Quellcode:
var myIP:string;
begin
  //Variante 1 (idIPWatch)
  with TidIPWatch.create(nil) do
  begin
    myIP:=LocalIP;
    free;
  end;
  memo1.lines.add(myIP);

  // Variante 2 (scktcomp)
  with TClientsocket.Create(nil) do
  begin
    myIP:=inttohex(Socket.LookupName('').S_addr,8);
    free;
  end;
  memo1.lines.add(myIP);

mjustin 18. Dez 2009 16:16

Re: Eigene IP Adresse ermitteln
 
Zitat:

Zitat von sirius
a) Man nutzt die gleichen Möglichkeiten, wie in einer Formularanwendung. --> Frage ist obsolet

TClientSocket/TServerSocket brauchen Windows Handles, die man in einer Formularanwendung reichlich hat - in einer Konsolenanwendung muss man sich irgendwo ein Handle "selber bauen" :)

Cheers,

sirius 18. Dez 2009 16:30

Re: Eigene IP Adresse ermitteln
 
Zitat:

Zitat von mjustin
Zitat:

Zitat von sirius
a) Man nutzt die gleichen Möglichkeiten, wie in einer Formularanwendung. --> Frage ist obsolet

TClientSocket/TServerSocket brauchen Windows Handles, die man in einer Formularanwendung reichlich hat - in einer Konsolenanwendung muss man sich irgendwo ein Handle "selber bauen" :)

Prinzipiell zwar ja , aber
1. Braucht der Code zum ermitteln einer IP mittels TClientsocket noch kein Fenster. Das geht definitv in jeder Konsole
2. Was nützt es, wenn ich ein Programm habe, was nur die IP ausgibt. Wenn TClientsocket auch noch für andere Sachen verwendet wird, ist auch in einer Konsole alles vorhanden
3. Das Handle liefert die Komponente, man selber muss nur die Messages empfangen.

Cicaro 18. Dez 2009 16:44

Re: Eigene IP Adresse ermitteln
 
Zitat:

Zitat von sirius
a) Man nutzt die gleichen Möglichkeiten, wie in einer Formularanwendung. --> Frage ist obsolet
b) In dieser Unit gibt es dafür keine Funktionen oder Methoden

zu a) Geimeint war eine sehr kleine Anwendung ohne jegliche Delphi-Komponenten
zu b) Komisch, deine Variante 2 ist genau das, was ich gesucht hab, und die Methode stammt aus dieser Unit. :thumb:

Also so funktioniert es für mich am besten:
Delphi-Quellcode:
var
  strIP: String;
  intIP: Integer;

begin
  with TClientSocket.Create(nil) do // TServerSocket geht auch
    begin
      intIP := Socket.LookupName('').S_addr;
      strIP := IntToStr(Byte(intIP)) + '.' + IntToStr(Byte(intIP shr 8)) + '.' + IntToStr(Byte(intIP shr 16)) + '.' + IntToStr(Byte(intIP shr 24));
      Free();
    end;
  Caption := strIP;
end;
Und ich hab nach der privaten IP Adresse gesucht. Die öffentliche ist die des Modem/Routers und die kann/will ich nicht wirklich für meinen Server benutzen.

Also demnach ist a), b) und c) beantwortet. Danke sirius!

TERWI 10. Feb 2016 16:56

AW: Eigene IP Adresse ermitteln
 
@Cicaro Sehr genial kurz und funktionell ! THX
Uses: ScktComp

RSF 10. Feb 2016 19:54

AW: Eigene IP Adresse ermitteln
 
Ich hatte einmal ein ähnliches Tool benötigt.
1. Lösung war eine einfache .bat Datei wo die IP in eine txt gespeichert wird.
ip.bat
Code:
@echo off & setlocal
REM set URL=http://checkip.dyndns.com/
set URL=http://meineip.softwareschuhmann.de
echo externe IP-Adresse wird ber %URL% ermittelt
echo und in die Datei IP.TXT gespeichert.
set G=%temp%\GetHTML.vbs
echo On Error Resume Next:Set Http=CreateObject("WinHttp.WinHttpRequest.5.1"):Http.Open "GET",WScript.Arguments(0),False:Http.Send:Q=Split(Http.ResponseText,":")(1):WScript.Echo Trim(Split(Q,"<")(0))>%G%
set ExtIP=
for /f %%i in ('cscript //nologo %G% "%URL%"') do set "ExtIP=%%i"
del %G%
if not defined ExtIP echo Externe IP konnte nicht ermittelt werden. & goto :eof
set PFAD=%~dp0
set DATEI=IP.txt
if exist %PFAD%%DATEI%  del /Q %PFAD%%DATEI% 
if not exist %PFAD%%DATEI%  echo %ExtIP%  > %PFAD%%DATEI%
echo ext. IP : %ExtIP%
2. Tool war notwendig um die DynDNS bei auf eigene Strato Seiten zu aktualisieren.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, winsock, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls, SHDocVw, StdCtrls, IdBaseComponent, IdComponent,
  IdTCPConnection, IdTCPClient, IdHTTP;

type
  TForm1 = class(TForm)
    btn1: TButton;
    Label1: TLabel;
    IdHTTP1: TIdHTTP;
    Label2: TLabel;
    IdHTTP2: TIdHTTP;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;

    procedure btn1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);


  private
    { Private-Deklarationen }

  public
    { Public-Deklarationen }


  end;

var
  Form1: TForm1;
  IPADRESSE:String;

const
  HOSTNAMEN='xxxx.xxxxxx.de';
  USERNAME ='xxxxxxxxxx';
  PASSWORT ='**********';


implementation

{$R *.dfm}



Function GeExtIP: string;
 var ndx: integer;

 begin
  //result:=uppercase(Form1.IdHTTP1.Get('http://checkip.dyndns.com'));
    result:=uppercase(Form1.IdHTTP1.Get('http://meineip.softwareschuhmann.de'));
    if result='' then result:='GET failed' else
    begin
      ndx:=pos(':',result);
      if ndx=0 then result:='host not found' else
        begin
           delete(result,1,ndx);
           delete(result,pos('<',result),Length(result));
           result:=trim(result);
        end;
      end;

 end;

Function UpdateIP: string; // für Strato
 begin
  Form1.IdHTTP2.Request.BasicAuthentication:=True;
  Form1.IdHTTP2.Request.Username:=USERNAME;
  Form1.IdHTTP2.Request.Password:=PASSWORT;
  result:=Form1.IdHTTP2.Get(Format('http://dyndns.strato.com'
  +'/nic/update?system=dyndns&hostname=%s&myip=%s'
  ,[HOSTNAMEN,IPADRESSE]));

 end;



procedure TForm1.btn1Click(Sender: TObject);
begin
 IPADRESSE:=GeExtIP;
 label1.Caption:= IPADRESSE;
 Label2.Caption:=UpdateIP;

end;

procedure TForm1.FormShow(Sender: TObject);
begin
 Label5.Caption:= HOSTNAMEN;
 btn1click(self);
end;

end.
vielleicht kann das jemand weiterverwenden.

Schwedenbitter 24. Feb 2016 15:15

AW: Re: Eigene IP Adresse ermitteln
 
Auf den Zug will/muss ich mal aufspringen:
Zitat:

Zitat von Astat (Beitrag 980727)
... Also wenn Du die IP ermitteln möchtest, musst du wissen von welchem Adapter du diese auslesen willst.

Beispiel Notebook:
W-Lan, NIC, ISDN, ADSL, Firewalls, Virenscanner, BlueTooth usw.
Hier kann es möglich sein, dass bis zu 7 IP's (Adaptoren) vorhanden sind.

Also Kurz und einfach, ohne sich genauer mit der Materie zu beschäftigen, wirds nicht gehen!

Wie kann ich das herausfinden?
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:
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;
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.

P.S. Ich finde übrigens diese überall zu findende Funktion nicht so furchtbar, dass man sich nach Java flüchten müsste.

Valle 24. Feb 2016 17:46

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:
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
Obacht: es kann auch mehrere Standardrouten geben. Nimm die mit höchster Priorität (kleinster Metrik).

BoolString 24. Feb 2016 18:46

AW: Eigene IP Adresse ermitteln
 
Was ist mit so was:
code10.info IP Adapter

Hab so was vor Jahren auch mal gebraucht und dort öffentlich gestellt...

Jan

Schwedenbitter 24. Feb 2016 20:01

AW: Eigene IP Adresse ermitteln
 
Zitat:

Zitat von Valle (Beitrag 1331258)
... 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:
C:\Users\Valentin>route PRINT -4
(...)
Obacht: es kann auch mehrere Standardrouten geben. Nimm die mit höchster Priorität (kleinster Metrik).

Das gefällt mir.
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:

Zitat von BoolString (Beitrag 1331262)
Was ist mit so was:
code10.info IP Adapter

Hab so was vor Jahren auch mal gebraucht und dort öffentlich gestellt...

Jan

So etwas weiß ich zu schätzen. Ich schaue mir das mal an. Metric scheint es in
Delphi-Quellcode:
tNetworkInterface
auf den ersten Blick dort nicht zu geben...

Danke soweit erstmal für Eure tollen Antworten!

Schwedenbitter 24. Feb 2016 20:24

AW: Eigene IP Adresse ermitteln
 
Zitat:

Zitat von Schwedenbitter (Beitrag 1331265)
... Ich schaue mir das mal an...

Mit Copy & Paste kann man den Code schnell testen.
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.

Valle 24. Feb 2016 22:30

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 das hier gezeigt. Suchbegriff ist vor allem "routing table", da findest du sicherlich noch was. :)

Schwedenbitter 24. Feb 2016 22:43

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. das und das gestoßen. So ziemlich am Ende steht etwas von einer APIPA-Adresse nach dem Muster 169.254.x.x. Ich habe jetzt festgestellt, dass die anderen Adapter genau eine solche bekommen. Die filtere ich also einfach aus und habe meine Adresse.

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.

Sir Rufo 25. Feb 2016 11:02

AW: Eigene IP Adresse ermitteln
 
Also der Code von
Zitat:

Zitat von BoolString (Beitrag 1331262)
Was ist mit so was:
code10.info IP Adapter

war ja schon echt übel zusammengeklopft :stupid:

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:
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.
Dazu gehört dann noch
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 05:38 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz