Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   IP Range (https://www.delphipraxis.net/65654-ip-range.html)

Luckie 19. Mär 2006 16:09


IP Range
 
Ich habe zwei IP Adressen: 192.168.2.100 und 192.168.5.100 Jeder Teil der IP Adresse liegt mir als Integer vor. Wie kann ich jetzt alle IP Adressen in diesem Bereich generieren? Ich habe da irgendwie gerade einen Blackout. :?

Frickeldrecktuxer_TM 19. Mär 2006 16:23

Re: IP Range
 
Zitat:

Zitat von Luckie
Ich habe zwei IP Adressen: 192.168.2.100 und 192.168.5.100 Jeder Teil der IP Adresse liegt mir als Integer vor. Wie kann ich jetzt alle IP Adressen in diesem Bereich generieren? Ich habe da irgendwie gerade einen Blackout. :?

kürze sie zu jeweils 4 bytes mache einen integer daraus und lasse von integer1 bis integer2 alle zahlen durchlaufen.
Delphi-Quellcode:
TIP = array[0..3] of Integer;

function makeip(IP: Integer): String;
begin
  result := IntToStr((IP shr 24) and $FF) + '.' + IntToStr((IP shr 16) and $FF) + '.' + IntToStr((IP shr 8) and $FF) + '.' + IntToStr((IP shr 0) and $FF);
end;

ip1_int := ((ip1[0] and $FF) shl 24) or ((ip1[1] and $FF) shl 16) or ((ip1[2] and $FF) shl 8) or ((ip1[3] and $FF) shl 0);
ip2_int := ((ip2[0] and $FF) shl 24) or ((ip2[1] and $FF) shl 16) or ((ip2[2] and $FF) shl 8) or ((ip2[3] and $FF) shl 0);

for i := ip1_int to ip2_int do
begin
  Memo1.Lines.Add(IntToStr(makeip(i));
end;

Luckie 19. Mär 2006 16:51

Re: IP Range
 
Mann bei dem ganzen rumgeschiebe wird einem ja schwindelig. Aber es geht. Ich glaube, ich hätte da was mit zeichenketten Routinen rumgebastelt. ;) Besten Dank.

Frickeldrecktuxer_TM 19. Mär 2006 16:57

Re: IP Range
 
Zitat:

Zitat von Luckie
Ich glaube, ich hätte da was mit zeichenketten Routinen rumgebastelt.

warum so kompliziert? :mrgreen: ipv4-adressen sind doch auch nur 32bit-integer wie jeder von uns sie täglich benutzt :-)
bei ipv6 hättest du schon mehr probleme denn da bräuchtest du erstmal einen 128bit datentyp ;-)

Frickeldrecktuxer_TM 19. Mär 2006 16:59

Re: IP Range
 
argh. mit fällt grad ein daß der Gebrauch von Integer als datentyp hier zu problemen führen kann. nimm lieber Cardinal/LongWord. aber ansonsten bleibt der code gleich.

Luckie 20. Mär 2006 00:08

Re: IP Range
 
Auch wenn ich es als LongWord deklariere, bekomme ich bei 192.168.2.100 - 255.255.255.255 einen "Range check error".

xaromz 20. Mär 2006 00:38

Re: IP Range
 
Hallo,

wie wär's hiermit:
Delphi-Quellcode:
type
  TIPAddr = array[0..3] of Byte;

function GetNext(var IPAddr: TIPAddr): Boolean;
var
  C: Integer;
begin
  Result := True;
  for C := 3 downto 0 do
  begin
    if IPAddr[C] < 255 then
    begin
      Inc(IPAddr[C]);
      Exit;
    end;
    IPAddr[C] := 0;
  end;
  Result := False;
end;

function IsBelowOrEqual(IP, Limit: TIPAddr): Boolean;
begin
  Result := (IP[0] shl 24 + IP[1] shl 16 + IP[2] shl 8 + IP[3]) <=
    (Limit[0] shl 24 + Limit[1] shl 16 + Limit[2] shl 8 + Limit[3]);
end;
Anwendung:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Start, Stop: TIPAddr;
begin
  Start[0] := 192;
  Start[1] := 168;
  Start[2] := 0;
  start[3] := 1;

  Stop[0] := 192;
  Stop[1] := 168;
  Stop[2] := 1;
  Stop[3] := 10;
  repeat
    ListBox1.Items.Add(IntToStr(Start[0]) + '.' + IntToStr(Start[1]) + '.' +
      IntToStr(Start[2]) + '.' + IntToStr(Start[3]));
    if not GetNext(Start) then
      Exit;
  until not IsBelowOrEqual(Start, Stop);
end;
Gruß
xaromz

Harry M. 20. Mär 2006 05:27

Re: IP Range
 
Hallo mein Lieber ;-)

Hätte nicht gedacht, das auch ich Dir mal weiter helfen kann.

Also zuerst die Integer-Werte wandeln is klar denke ich dann kannst du die CreateIPPool benutzen.

Wichtig zu wissen: Die CreateIPPool war die Beste von 3 Versuchen mit dem besten zeitlichen Ergebenissen. Von ?.0.0.0 ?.50.255.255 benötigt sie ca 3-4 sek. Je nach CPU. Die anderen Versuche kommen dabei immer so um die 10-15 Sek weg. Villeicht bekommst Du sie ja noch schneller :-).
In dem Fall lass von Dir hören.

Delphi-Quellcode:
type
  PIp = record
    p1 : String;
    P2 : String;
    p3 : String;
    p4 : String;
    end;

type
 MyIP = packed record
  case Byte of
    0: (D,C,B,A : Byte);
    1: (dwValue : DWord);
  end;

function SplittIP(IP: string): PIp;
var
  I: Integer;
begin
  Result.p1 := '';
  Result.p2 := '';
  Result.p3 := '';
  Result.p4 := '';

  I := 0;
  repeat
    Inc(I, 1);
    if IP[I] <> '.' then
      Result.p1 := Result.p1+IP[I];
  until
     IP[I] = '.';

  repeat
    Inc(I, 1);
    if IP[I] <> '.' then
      Result.p2 := Result.p2+IP[I];
  until
     IP[I] = '.';

  repeat
    Inc(I, 1);
    if IP[I] <> '.' then
      Result.p3 := Result.p3+IP[I];
  until
     IP[I] = '.';

  repeat
    Inc(I, 1);
    if IP[I] <> '.' then
      Result.p4 := Result.p4+IP[I];
  until
     I = Length(IP);
end;

function CreateIPPool(sStartIp, sEndIp: String): TStringList;
var
 FromIP, ToIP, IP: MyIP;
 I: Integer;
 Adress: PIp;
begin
  Result := TStringList.Create;
  Adress := SplittIP(sStartIp);
  with FromIP do begin
    A := StrToInt(Adress.p1);
    B := StrToInt(Adress.p2);
    C := StrToInt(Adress.p3);
    D := StrToInt(Adress.p4);
    end;

  Adress := SplittIP(sEndIp);
  with ToIP do begin
    A := StrToInt(Adress.p1);
    B := StrToInt(Adress.p2);
    C := StrToInt(Adress.p3);
    D := StrToInt(Adress.p4);
    end;

  for I := FromIP.dwValue to ToIP.dwValue do begin
    IP.dwValue := I;
    with IP do
      Result.Add(Format('%d.%d.%d.%d',[A,B,C,D]));
    end;
end;

negaH 20. Mär 2006 05:33

Re: IP Range
 
man kann es auch kompiliziert machen. Warum addiert ihr nicht gleich mit den Strings ? Ist doch bestimmt kein Aufwand mit IP in Strings zu rechnen ;) (sarkasmus off)


Gruß Hagen

Delphi-Quellcode:
function ToIP(I1,I2,I3,I4: Integer): Cardinal;

  function Check(Value: Integer): Byte;
  begin
    if (Value >= 0) and (Value <= 255) then Result := Value
      else raise Exception.Create('ToIP: Values I1,I2,I3,I4 must be in Range 0 upto 255 each');
  end;

begin
  Result := Check(I1) shl 24 or Check(I2) shl 16 or Check(I3) shl 8 or Check(I4);
end;


function IPToStr(Value: Cardinal): String;
begin
  Result := Format('%d.%d.%d.%d', [Value shr 24, Value shr 16 and $FF, Value shr 8 and $FF, Value and $FF]);
end;


procedure Test;
var
  IP: Cardinal;
begin
  for IP := ToIP(192,168,2,100) to ToIP(192,168,5,100) do
    Writeln( IPToStr(IP) );
end;

Harry M. 20. Mär 2006 05:50

Re: IP Range
 
Weil es zulangsam ist!!
Habs grad mal getest: ?.0.0.0 ?.50.255.255: nach über 4 Minuten CPU-Zeit habe ich den das Programm zurückgesetzt...

marabu 20. Mär 2006 05:52

Re: IP Range
 
Guten Morgen.

Kennt denn keiner mehr die Standard-Routinen inet_addr() und inet_ntoa() aus der Unit WinSock?

Nachdenkliche Grüße vom marabu

negaH 20. Mär 2006 06:07

Re: IP Range
 
Zitat:

Weil es zulangsam ist!!
Habs grad mal getest: ?.0.0.0 ?.50.255.255: nach über 4 Minuten CPU-Zeit habe ich den das Programm zurückgesetzt...
Dann darf mann nicht Äpfel mit Birnen vergleichen. Lass mich mal raten: du hast mit den WriteLn(IPToStr(IP)); getestet ? Dann vergleiche das mal mit deiner Methode die ebenfalls WriteLn() benutzt.
Logisch müssen deiner und mein Code fast identisch effizient sein mit dem Unterschied das es mit garnicht sonderlich um Effizienz im Laufzeitverhalten ging sondern um Effizienz im Sourcecode: sprich Überprüfungen, Vermeidung von Rangecheck Errors, sauberer Borland konformer Source.

@marabu: ich weis, denke aber das Luckie das selber machen wollte und eventuell die Unit WinSocks nicht einlinken will. Ich persönlich vermeide es immer WinSocks einzulinken wenn es sich vermeiden lässt. Das Problem ? ganz einfach weil die WinSocks DLLs wohl diejenigen DLLs im Windows sind die am meisten durch 3'rd Party Tools wie Virenscanner, Firewalls, ISDN Treiber, USB Treiber und Trojaner ausgetauscht bzw. sidelinked sind. Man lädt sich also mit WinSocks ohne es zu merken eventuell miesen Code in seine Anwendung.

Gruß Hagen

Harry M. 20. Mär 2006 06:10

Re: IP Range
 
Gut mir ging es damals bei der Entwicklung nur rein um Geschwindigkeit ;-)

negaH 20. Mär 2006 06:15

Re: IP Range
 
Begründung:

Gruß Hagen

Delphi-Quellcode:

type
  PIp = record    // <- TYPEN fangen mit T an
    p1 : String;
    P2 : String;
    p3 : String;
    p4 : String;
    end;         // <- Einrückungen, ein Block immer auf gleicher Höhe

type
MyIP = packed record  // <- Einrückungen
  case Byte of
    0: (D,C,B,A : Byte);
    1: (dwValue : DWord);
  end;

function SplittIP(IP: string): PIp; // <- String ist eigener Type also S groß bei String
var
  I: Integer;
begin
  Result.p1 := '';
  Result.p2 := '';
  Result.p3 := '';
  Result.p4 := '';

  I := 0;
  repeat
    Inc(I, 1);
    if IP[I] <> '.' then           // <- Hier AV bei IP = ''
      Result.p1 := Result.p1+IP[I]; // <- Leerzeichen zwischen Operatoren, alles am + geklitscht
  until
     IP[I] = '.';                  // <- eine Zeile höher, ist ja wohl nur schlecht
....
end;

function CreateIPPool(sStartIp, sEndIp: String): TStringList;
var
FromIP, ToIP, IP: MyIP; // <- Einrückungen
I: Integer;
Adress: PIp;
begin
  Result := TStringList.Create; // <- Allokation und Rückgabe von komplexen Datentypen sollte man vermeiden
                                 // besser ist es als Paramater Strings: TStrings zu übergeben damit der Aufrufer
                                 // der Funktion für die Datenhaltung verantwortlich bleibt.
  Adress := SplittIP(sStartIp);
  with FromIP do begin          // <- begin markiert einen neuen Source/Formtierungs Block, gehört in die nächste
                                 // Zeile direkt unter das with.
    A := StrToInt(Adress.p1);
    B := StrToInt(Adress.p2);
    C := StrToInt(Adress.p3);
    D := StrToInt(Adress.p4);
    end;

  Adress := SplittIP(sEndIp);
  with ToIP do begin
    A := StrToInt(Adress.p1);
    B := StrToInt(Adress.p2);
    C := StrToInt(Adress.p3);
    D := StrToInt(Adress.p4);
    end;

  for I := FromIP.dwValue to ToIP.dwValue do begin // <- begin
    IP.dwValue := I;
    with IP do
      Result.Add(Format('%d.%d.%d.%d',[A,B,C,D]));
    end;
end;

Sharky 20. Mär 2006 06:21

Re: IP Range
 
Hai Luckie,

mal eine Frage zu deinen IPs.
Warum brauchst Du denn die Adressen aus zwei verschiedenen Netzen?
Du hast das Netz 192.168.2.0 und 192.168.5.0 die beiden haben doch nichts miteinaner zu tun.
Oder sollte das ganze nur ein Beispiel für deinen "PINGer" sein?

phXql 20. Mär 2006 06:30

Re: IP Range
 
Zitat:

Zitat von negaH
Begründung:

Hi Hagen,

meiner Meinung nach wird string NICHT mit einem großen S geschrieben. Bei delphi ist string ein keyword (wird ja auch fett gemacht), und keywords schreibt man nunmal klein...

negaH 20. Mär 2006 06:39

Re: IP Range
 
das ist tatsächlich eine Ansichtssache. Es ist ein Bezeichner und müsste klein geschrieben werden das stimmmt. Allerdings arbeite ich seit Borland Pascal 4.2 und orientiere mich immer an dem Stil der Borlandianer. Wobei man sagen muß das die letzten Entwicklungen im Hause Borlnd nicht mehr als Referenz dienen können da die Sourcen immer schlechter geworden sind.

Es geht mir aber hier garnicht um solche Kleinigkeiten. Am wichtigsten ist der Fakt das obige Funktion bei IP = '' eine Zugriffsschutzverletzung erzeugen muss !! Übrigens muß ich dazu nichtmal den Source testen, lesen reicht schon aus um dies zu sehen.

Sorry, ich möchte hier keinen Krieg anzetteln. Jeder soll nach seinen Ansprüchen seine privaten Source bauen können wie er es möchte. Allerdings ist dies hier ein Forum und viele Anfänger orientieren sich in ihrem Programmierstil an solchen Beispielen wir hier gezeigt. Es ist also in unser aller Interesse wenn wir Sourcecode-technisch hier in der DP ein hohes Niveau hinbekommen könnten.

Zb. die Angewohnheit das begin NICHT in einer eigenen Zeile einzurücken ist schätzungsweise höchsten 8-10 Jahre alt. Davor wurde immer das begin eingerückt, bzw. mir persönlich sind keine Sourcen bekannt vor dieser zeit die es nicht einrückten. Leider hat sich diese Unart sehr schnell verbreitet.

Ok back to topic now, and sorry Luckie.

Gruß Hagen

Harry M. 20. Mär 2006 06:56

Re: IP Range
 
Zitat:

Zitat von negaH
TYPEN fangen mit T an

Stimmt. Ist ein Fehler von mir, weil ích halt auch nicht perfekt bin. Der Code ist noch aus ner alten Testphase wo ich noch mit Pointern spielte um zusehen was am Ende schneller ist.

Der Fainess halbe habe ich jetzt mal kurz das writeln gegen eine TStringList getauscht. Stimmt. Ich konnte die range innherhalb von 4547ms erzeugen. Ich muss aber dazu sagen das die CPU hier, wo ich grad bin etwas lahmer is als meiner da heim. Also könnte sie doch in etwas die Gleiche Effizienz haben.

Was die Zugriffsverletzung angeht: Habe ich bis heute nicht gesehen. Das Progie wo ich diesen Code reincomiliert habe läuft schon seit Monaten. Problemlos!

Luckie 20. Mär 2006 07:28

Re: IP Range
 
@Sharky: Ja das ist ein Beispiel für mein Pi9ng Programm. Warum sollte man nicht gleich verschiedenen Netze damit durchpingen wollen? ;)

marabu 20. Mär 2006 09:06

Re: IP Range
 
Hallo Hagen,

Zitat:

Zitat von negaH
ich weis, denke aber das Luckie das selber machen wollte und eventuell die Unit WinSocks nicht einlinken will.

stimmt, Luckie macht es manchmal gerne zu Fuß - aber wenn es um das Ping-Tool geht, da hat er WinSock eingebunden.

Zitat:

Zitat von negaH
Ich persönlich vermeide es immer WinSocks einzulinken wenn es sich vermeiden lässt.

Das glaube ich dir, aber nicht jeder kann sich diese Haltung leisten. Ich arbeite in einem managed environment. Meine Zeit in der DP erwirtschafte ich z.B. durch den Aufruf von inet_addr() anstatt 30 Zeilen eigenen Code zu schreiben. Das drückt meine Lines-Of-Code und damit meine Fehlerrate. Oft bewundere ich deine Vorgehensweise, aber es gibt Bereiche abseits deines Spezialgebietes, in denen man andere Prioritäten setzen muss, damit man nicht abgestraft wird.

Du hast in deinem Beitrag #17 über den Vorbildcharakter von publizierten Quellen für Anfänger geschrieben. Gerade bei Anfängern beobachte ich eine gewisse Dankbarkeit für Hinweise, wie man mit dem Aufruf von wenigen System-Routinen eigenen, mit Schweiß und Tränen geschriebenen Code mehrerer Tage ersetzen kann.

Freundliche Grüße vom marabu

Luckie 20. Mär 2006 09:15

Re: IP Range
 
Stimmt, die WinSock brauche ich sowieso. Aber man will ja auch noch was lernen.

Aber warum bekomme ich bei 192.168.100.1 - 255.255.255.255 immer noch einen "Fehler bei der Bereichsprüfung"?

marabu 20. Mär 2006 09:47

Re: IP Range
 
Hallo Michael,

welchen Code verwendest du inzwischen? Hast du mal einen Brechpunkt gesetzt?

marabu

Sharky 20. Mär 2006 09:49

Re: IP Range
 
Zitat:

Zitat von Luckie
... - 255.255.255.255 ...

Hai Luckie,

Du solltest aber in jedem Fall prüfen ob es überhaupt gültige IPs sind. 255.255.255.255 ist zum Beispiel keine gültige Hostadresse.

Klaus01 20. Mär 2006 09:53

Re: IP Range
 
255.255.255.255 ist wohl die Netsmaske

Grüße
Klaus

Luckie 20. Mär 2006 09:55

Re: IP Range
 
Oh, bis wann geht denn eine gültige IP Adresse?

Sharky 20. Mär 2006 10:00

Re: IP Range
 
Zitat:

Zitat von Luckie
Oh, bis wann geht denn eine gültige IP Adresse?

Es geht nicht um eine gültige IP-Adresse sondern um eine gültige Host-Adresse ;-)

Diese Frage kann man nicht so einfach beantwortet ;-)

255.255.255.255 ist auf jeden Fall die Multicast Adresse. Das IP-Packet wird also in der Theorie an jeden Rechner gesendet.

Es gilt eigentlich:
Die Hostadresse ist der Teil einer IP-Adresse bei denen die Bits der Subnetmakse 0 sind.

IP: 192.168.001.xxx
SM: 255.255.255.000

Hostteil der IP: .xxx
Netzteil der IP 192.168.001

Es gilt: Wenn alle Bits des Hostteiles 0 sind ist dies die "Netzwerkadresse". Sind alle Bits = 1 ist dies die Broadcastadresse.

In diesem Fall ist also:
Netzwerkadresse = 192.168.1.0
Broadcastadresse = 192.168.1.255

Gültige Hostadressen sind 192.168.1.1 bis 192.168.1.254

EDIT
Lese mal hier ab dem Abschnitt Netzklassen.

Klaus01 20. Mär 2006 10:14

Re: IP Range
 
Zitat:

255.255.255.255 ist auf jeden Fall die Multicast Adresse. Das IP-Packet wird also in der Theorie an jeden Rechner gesendet
In der Praxis wird dieses IP-Paket an jeden Rechner gesendet der in der entprechenden Multicastgruppe ist.
Broadcast -> an alle
Multicast -> an einige oder viele

Grüße
Klaus

negaH 21. Mär 2006 15:06

Re: IP Range
 
Marabu hat mich in einer PN einen wichtigen Umstand klargemacht den ich schon wieder vergessen hatte !

Die IPs werden auf einem MS Windows Rechner im WinSocks entgegen dem Standard in einen 4 Bytes Cardinal gespeichert.

130.094.122.195 -> binär 10000010 01011110 01111010 11000011 -> Hex $82,$5E,$7A,$C3 als Cardinal als $825E7AC3.

Das Windows WinSocks speichert aber dagegen $C37A5E82 !
Wenn man also mit WinSocks arbeitet und dessen IP Adressdaten zb. Type TInAddr aus inet_ntoa(), oder eben zb. inet_addr(130.094.122.195) benutzen möchte so MUSS man mit htonl() und/oder ntohl() das vorher konvertieren.
Das ist wichtig da man ansonsten in einer Schleife ganz falsche Bereiche scannt.

In meinen vorherigen Source habe ich mich an die Standardkodierung gehalten und entgegen dem WinSock zb. die Addresse 130.094.122.195 in einen Cardial mit $825E7AC3 umgewandelt. Somit kann man mit diesem Wert auch in einer Schleife arbeiten ohne Probleme.

Es ist also kein Fehler wenn

Delphi-Quellcode:
   IPtoStr( inet_addr( PChar('130.094.122.195')));
statt 130.094.122.195 eben 195.122.094.130 ausspuckt da bei Verwendung vom WinSock es richtig lauten muß

Delphi-Quellcode:
   IPtoStr( ntohl( inet_addr( PChar('130.094.122.195')) ));
Gruß Hagen


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:11 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