?
Solved

IP to Decimal and Decimal to IP

Posted on 2003-02-23
26
Medium Priority
?
1,929 Views
Last Modified: 2013-11-13
Does anyone have a function that converts an IP to Decimal and a function that converts the decimal back to IP


Thanks

0
Comment
Question by:alspivey
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
  • 3
  • +6
26 Comments
 
LVL 101

Expert Comment

by:mlmcc
ID: 8006009
What is an IP?

mlmcc
0
 

Author Comment

by:alspivey
ID: 8006077
Internet address i.e 192.168.0.1
0
 
LVL 84

Expert Comment

by:ozo
ID: 8006511
perl -e "print unpack'N',pack'C*',split/\./,shift" 192.168.0.1
perl -e "print join'.',unpack'C*',pack'N',shift" 3232235521
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:cincin77
ID: 8007098
in C/C++ try inet_aton:
 inet_aton() converts the Internet host address cp from the standard numbers-and-dots notation into  binary  data  and
       stores it in the structure that inp points to. inet_aton returns nonzero if the address is valid, zero if not.


 #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>
 
       int inet_aton(const char *cp, struct in_addr *inp);
0
 

Expert Comment

by:Whacko
ID: 8007407
heres an ip to decimal delphi function i made some time ago. Tho i dont quite know how to reverse it :P

var
  Dec   : Array[1..4] of integer = (16777216,65536,256,1);


procedure ip2dec(ip:string; decimal: int64);
VAR ip             : Array[1..4] of Int64;
    IPCut          : string;
    Poz, i         : integer;
    total          : int64;

begin
   IPCut := ipstr;

   i := 1;
   While Pos('.', IPCut) > 0 Do
   Begin
     Poz := Pos('.', IPCut);
     ip[i] := StrToInt( Copy(IPCut,1,Poz - 1));
     Delete(IPCut, 1, Poz);
     inc(i);
   end;
   ip[4] := StrToInt(IPCut);

   Total := 0;
   i := 1;
   While i <= 4 do
   begin
     total := Total + ip[i] * dec[i];
     inc(i);
   end;
   decimal := total;
end;
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8008915
Delphi code:

type
  // since IPv4 address consists of four octets or simply dword
  TIPv4 = record
    a,b,c,d: byte;
  end;

function IPv4ToInt(const IP: string): dword;
var
  c, i, l: integer;
  ba: array [0..3] of byte;
  s: string;
begin
  c := 0;
  l := Length(IP);
  for i := 1 to l do begin
    if IP[i] <> '.' then
      s := s + IP[i];
    if (IP[i] = '.') or (i = l) then begin
      ba[c] := StrToInt(s);
      s := '';
      inc(c);
    end;
  end;
  Move(ba, Result, 4);
end;

function IntToIPv4(const IntIP: dword): string;
begin
  with TIPv4(IntIP) do
    Result := Format('%d.%d.%d.%d', [a, b, c, d]);
end;

wbr, mo.
0
 

Author Comment

by:alspivey
ID: 8009553
Internet address i.e 192.168.0.1
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8009667
IPv4ToInt('192.168.0.1') will be 16820416.
IPv4 is in format xxx.xxx.xxx.xxx
where xxx is 8bit number (octet)

wbr, mo.
0
 
LVL 24

Expert Comment

by:SunBow
ID: 8010688
done?
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8010801
I think, first you must specify what language you are using ;-). The following example (in Delphi) I used for my own needs:

uses
  Splitter;

type
  TIPAddress = packed record // IP-àäðåñ
    case Integer of
      1: (A4, A3, A2, A1: Byte);
      2: (A: Cardinal);
  end;

function GetIPFromString(S: String): TIPAddress;
var
  Splitter: TSplitter;
  Code, A: Integer;
  IP: TIPAddress;
label 1;
begin
  Result.A := 0;
  Splitter := TSplitter.Create(S, '.', True);
  if Splitter.Src = '' then Goto 1;
  if Splitter.Count <> 4 then Goto 1;
  if Splitter.S[0] = '*' then IP.A1 := 255 else
  begin
    Val(Splitter.S[0], A, Code);
    if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
    IP.A1 := A;
  end;
  if Splitter.S[1] = '*' then IP.A2 := 255 else
  begin
    Val(Splitter.S[1], A, Code);
    if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
    IP.A2 := A;
  end;
  if Splitter.S[2] = '*' then IP.A3 := 255 else
  begin
    Val(Splitter.S[2], A, Code);
    if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
    IP.A3 := A;
  end;
  if Splitter.S[3] = '*' then IP.A4 := 255 else
  begin
    Val(Splitter.S[3], A, Code);
    if (Code <> 0) or (A < 0) or (A > 255) then Goto 1;
    IP.A4 := A;
  end;
  Result := IP;
1:
  Splitter.Free;
end;

function GetStringFromIP(IP: TIPAddress): String;
begin
  Result := IntToStr(IP.A1) + '.' + IntToStr(IP.A2) + '.' + IntToStr(IP.A3) +
                                                          '.' + IntToStr(IP.A4);
end;

Splitter unit source may be obtainet here: http://www.serge.dsip.net/downloads/Splitter.pas

If you are using WinSock API you may prefer WinSock API native functions inet_addr and inet_ntoa (given C++ syntax):

char FAR * inet_ntoa (
  struct   in_addr in  
);

unsigned long inet_addr (
  const char   FAR *cp  
);

See Platform SDK: Windows Sockets (MSDN) for details.
0
 

Expert Comment

by:Whacko
ID: 8010934
i think he should choose the SHORT solution :P
0
 

Author Comment

by:alspivey
ID: 8012389
Hi mocarts,

Your 2 functions work great. What I'm trying to do is calculate how many ip's are contained in a range of 2 address i.e 192.168.0.8 - 192.168.1.255. And I was thinking that converting them to decimal would alow me to subtract them to get the total count. (How wrong I was)
I also was trying to step through the IP's one by one by adding 1 to the decimal and then convert it back, but that want work. Any ideas on how to do something this.

p.s msa2003 I'm using Delphi
0
 
LVL 8

Expert Comment

by:akshayxx
ID: 8014742
u shud have specified the language of ur choice.. else everyday u'll get a solution in different programming language
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8015545
that's very simple.
example with functions provided above by me:

function CountIPs(const ipFrom, ipTo: string): int64;
var
  ipf, ipt: TIPv4;
begin
  Result := 0;
  ipf := TIPv4(IPv4ToInt(ipFrom));
  ipt := TIPv4(IPv4ToInt(ipTo));
  Result := ((ipt.a-ipf.a)*16777216) + ((ipt.b-ipf.b)*65536)
    + ((ipt.c-ipf.c)*256) + (ipt.d-ipf.d) {+ 1};
  // +1 - if you want to include ipFrom in range
end;

and function to increment by one IP:
procedure IncIPv4(var IP: TIPv4);
begin
  if IP.d < 255 then Inc(IP.d)
    else begin
      IP.d := 0;
      if IP.c < 255 then Inc(IP.c)
      else begin
        IP.c := 0;
        if IP.b < 255 then Inc(IP.b)
        else begin
          IP.b := 0;
          if IP.a < 255 then Inc(IP.a)
            else IP.a := 0;
        end;
      end;
    end;
end;

wbr, mo.
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8018293
Whacko: my solution is not big. It is universal. Because I used it to work with real sets of IP addresses.

You should use my unit the next way:

Count := Abs(GetIPFromString('192.168.0.8').A - GetIPFromString('192.168.1.255').A);

Very simple, isn't it ;-) ?

Mocart: Don't you think that there is no need to get values by multiplication? I think that the better way (which does exactly the same, but much faster) is to use packed record to set a byte of a double word ;-).

The shorter example (excluding masking and error checking) of GetIPFromString:

function GetIPFromString(S: String): TIPAddress;
var
 Splitter: TSplitter;
 Code: Integer;
begin
 Splitter := TSplitter.Create(S, '.', True);
 Val(Splitter.S[0], Result.A1, Code);
 Val(Splitter.S[1], Result.A2, Code);
 Val(Splitter.S[2], Result.A3, Code);
 Val(Splitter.S[3], Result.A4, Code);
 Splitter.Free;
end;
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8018346
And what is really better:

uses
  WinSock;

function CountIPs(const ipFrom, ipTo: String): Integer;
begin
  Result := Abs(htonl(inet_addr('1.1.1.2')) - htonl(inet_addr('1.1.1.1')));
end;

The only one line of code ;-)

Whi don't I use Int64 - because IPv4 IP address is 32-bit!

htonl and inet_addr are WinSock API functions. inet_addr gets an IP address from it's string representation in reverse byte order. htonl converts it to normal byte order.
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8018371
Sorry,

uses
 WinSock;

function CountIPs(const ipFrom, ipTo: String): Integer;
begin
  Result := Abs(htonl(inet_addr(ipFrom)) - htonl(inet_addr(ipTo)));
end;
0
 
LVL 9

Accepted Solution

by:
mocarts earned 800 total points
ID: 8019122
you are right msa2003! I have to change order of elements in my TIPv4 record.
there will be complete solution to convert to dword and back IP string.

type
 {$IFOPT R-}
   {$DEFINE RANGEOFF}
 {$ENDIF}
 EInvalidIPString = class(Exception)
 end;

 TIPv4 = record
   d,c,b,a: byte;
 end;

function IPv4ToInt(const IP: string): dword;
var
 c, i, l: integer;
 ba: array [0..3] of byte;
 s: string;
begin
 c := 3;
 l := Length(IP);
 if l = 0 then raise EInvalidIPString.Create('Zero IP string length.');
 try
 for i := 1 to l do begin
   if IP[i] <> '.' then
     s := s + IP[i];
   if (IP[i] = '.') or (i = l) then begin
     {$IFDEF RANGEOFF} {$R+} {$ENDIF}
     ba[c] := StrToInt(s);
     {$IFDEF RANGEOFF} {$R-} {$UNDEF RANGEOFF} {$ENDIF}
     s := '';
     dec(c);
   end;
 end;
 except
   raise EInvalidIPString.Create('Invalid IP string format.');
 end;
 if c <> -1 then
   raise EInvalidIPString.Create('Invalid IP string format.');
 Move(ba, Result, 4);
end;

function IntToIPv4(const IntIP: dword): string;
begin
 with TIPv4(IntIP) do
   Result := Format('%d.%d.%d.%d', [a, b, c, d]);
end;

to get count:
  Count := IPv4ToInt(sIpTo) - IPv4ToInt(sIpFrom);

to increment:
  IntToIPv4(IPv4ToInt(sIP)+1);

wbr, mo.
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8020202
Don't you think that alltrhough usage of WinSock unit (which is shipped with Delphi) is better:

To get a string from IP (now Delphi syntax):
function inet_ntoa(in: in_addr): String;

To get an IP from string:
function inet_addr(cp: string): Cardinal;

To increment the IP address:
function inc_ip(ip: string): string;
var
  addr: in_addr;
begin
  addr.S_addr := htonl(htonl(inet_addr(ip)) + 1);
  Result := inet_ntoa(addr);
end;
0
 

Expert Comment

by:Whacko
ID: 8020803
no, cos if there's an old, or no winsock installed you might get errors :P also its always better to use code instead of (third party) components, because:
1. you learn more from it.
2. easier to debug cos you still know what you did.
3. users of your app wouldbt have to install extra dll's etc, just because you wanted to make an app the easy way.

if its only for personal use... just see for yourself, but i can recommend this to anyone who wants to "master" a programming language
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8023059
Yes, but i think different:
1. It is usefull to learn more about WinSock API, cos it is a native TCP/IP API
2. You still know what you did - dll's are already debugged :P
3. winsock32.dll is allwais provided with ANY 32-bit Windows system. If your system is not 32-bit, all these examples wouldn't work :P

Of course, the ways could be different. I think I provided both :-) So there is something to choose from ;-)

P. S. I could provide access to full code of my Utils unit (Splitter is just a part). This code provides extended functionality such as IP masked compare, IP sets, configuration and user management utilities etc. As a kernel it uses the functions provided ahead.
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8032117
since I use dword as result - function will work on 16, 32, 64 etc. bit systems.
of course Winsock is another way how to do it, but if you don't need Winsock why compile unit in app?
wbr, mo.
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8034457
mocarts: I noted that I had provided two different solutions. The first (with Splitter unit) doesn't use WinSock and is a part of a real billing system which is extremely stable and processes thowsands IP's every day ;-). Another solution uses functions already provided with Windows system.

Your solution will not work in 16-bit system ;-). Simoly bacause Delphi from version 2 generates ONLY 32-bit code ;-). Delphi (1) generates 16-bit code but doesn't has rather different syntax ;-).

There are the details. In the matter of fact there is not a market but a place where experts must exchange ;-).
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8034538
why did you think, code will not work on 16bit system? dword is 32bit on 16bit or on 32bit system it doesn't matter..
wbr, mo.
0
 
LVL 9

Expert Comment

by:mocarts
ID: 8057845
0
 
LVL 5

Expert Comment

by:msa2003
ID: 8059490
No thanx...
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
This video teaches viewers about errors in exception handling.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Suggested Courses

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question