WARNUNG : Die aus der akzeptierten Antwort resultierenden Ganzzahlen sind falsch , da die IP-Adressen in der Netzwerkreihenfolge (Big-Endian) vorliegen, während ints auf den meisten Systemen Little-Endian sind. Sie müssen also die Bytes vor dem Konvertieren umkehren. Siehe meine Antwort für korrekte Konvertierungen. Auch für IPv4 intkönnen keine Adressen gespeichert werden 127.255.255.255, die größer als z. B. die Broadcast-Adresse sind. Verwenden Sie daher a uint.
Saeb Amini
Antworten:
137
32-Bit-Ganzzahlen ohne Vorzeichen sind IPv4-Adressen. Während die IPAddress.AddressEigenschaft veraltet ist, ist sie eine Int64, die den vorzeichenlosen 32-Bit-Wert der IPv4-Adresse zurückgibt (der Haken ist, dass sie in der Reihenfolge der Netzwerkbytes vorliegt, sodass Sie sie austauschen müssen).
Zum Beispiel ist meine lokale google.com bei 64.233.187.99. Das entspricht:
64*2^24+233*2^16+187*2^8+99=1089059683
Und in der Tat, http: // 1089059683 / funktioniert wie erwartet (zumindest unter Windows, getestet mit IE, Firefox und Chrome; funktioniert jedoch nicht auf dem iPhone).
Hier ist ein Testprogramm, um beide Konvertierungen anzuzeigen, einschließlich des Austauschs von Netzwerk- / Host-Bytes:
using System;
using System.Net;classApp{staticlongToInt(string addr){// careful of sign extension: convert to uint first;// unsigned NetworkToHostOrder ought to be provided.return(long)(uint)IPAddress.NetworkToHostOrder((int)IPAddress.Parse(addr).Address);}staticstringToAddr(long address){returnIPAddress.Parse(address.ToString()).ToString();// This also works:// return new IPAddress((uint) IPAddress.HostToNetworkOrder(// (int) address)).ToString();}staticvoidMain(){Console.WriteLine(ToInt("64.233.187.99"));Console.WriteLine(ToAddr(1089059683));}}
In Opera 11 unter Ubuntu Linux 10.04 bestätigt: Es konvertiert das int zurück in die bekannte wxyz-Form und es funktioniert.
Piskvor verließ das Gebäude
6
IPAddress.Address ist ab .Net 4.0 veraltet .
Erik Philips
@ErikPhilips Ist das wichtig, wenn Sie nur IPv4 verwenden?
Ray
Das ist eine architektonische Entscheidung. Es hat Vor- und Nachteile, und Kommentare sind nicht der beste Ort, um dieses spezielle Thema zu diskutieren.
Erik Philips
1
Sie können BitConverter.ToUInt32 (IPAddress.Parse (Wert) .GetAddressBytes (). Reverse (). ToArray () verwenden, um IPAddress.Address ist veraltet
Mhmd
43
Hier sind zwei Methoden zum Konvertieren von IPv4 in eine korrekte Ganzzahl und zurück:
publicstaticuintConvertFromIpAddressToInteger(string ipAddress){var address =IPAddress.Parse(ipAddress);byte[] bytes = address.GetAddressBytes();// flip big-endian(network order) to little-endianif(BitConverter.IsLittleEndian){Array.Reverse(bytes);}returnBitConverter.ToUInt32(bytes,0);}publicstaticstringConvertFromIntegerToIpAddress(uint ipAddress){byte[] bytes =BitConverter.GetBytes(ipAddress);// flip little-endian to big-endian(network order)if(BitConverter.IsLittleEndian){Array.Reverse(bytes);}returnnewIPAddress(bytes).ToString();}
IP-Adressen sind in der Netzwerkreihenfolge (Big-Endian), während ints unter Windows Little-Endian sind. Um einen korrekten Wert zu erhalten, müssen Sie die Bytes umkehren, bevor Sie sie auf einem Little-Endian-System konvertieren.
Auch selbst für IPv4eine intnicht halten können Adressen größer als 127.255.255.255zB die Broadcast - Adresse (255.255.255.255), so verwendet ein uint.
Dies scheint unter Windows mit .NET keinen Unterschied zu machen - unsicher über Mono. Siehe dotnetfiddle.net/cBIOj2
Jesse
2
@Jesse es macht keinen Unterschied für Ihre Eingabe von, 1.1.1.1weil sein Byte-Array palindromisch ist. Versuchen Sie es mit nicht palindromischen wie 127.0.0.1oder 192.168.1.1.
Saeb Amini
Ich sehe das Problem. Wiederholte Zahlen wie 1.1.1.1, 2.2.2.2, 123.123.123.123ergeben immer das gleiche Ergebnis. Für die Nachwelt siehe aktualisierte Geige: dotnetfiddle.net/aR6fhc
Jesse
Ich möchte darauf hinweisen, dass ich verwenden musste System.Net.IPAddress, um dies zum Laufen zu bringen. Funktioniert super!
Shrout1
1
@ Jesse, das wäre nicht nur zum Wiederholen von Zahlen, sondern für alle palindromischen IP-Adressen. Das 2.1.1.2wäre auch so.
Saeb Amini
40
@Barry Kelly und @Andrew Hare, eigentlich denke ich nicht, dass Multiplikation der klarste Weg ist, dies zu tun (obwohl richtig).
Eine Int32 "formatierte" IP-Adresse kann als die folgende Struktur angesehen werden
[StructLayout(LayoutKind.Sequential,Pack=1)]structIPv4Address{publicByte A;publicByte B;publicByte C;publicByte D;}// to actually cast it from or to an int32 I think you // need to reverse the fields due to little endian
Um die IP-Adresse 64.233.187.99 zu konvertieren, können Sie Folgendes tun:
Sie können sie also mit + addieren oder binairy oder sie zusammen verwenden. Das Ergebnis ist 0x40E9BB63 (1089059683). (Meiner Meinung nach ist es viel einfacher, die Bytes zu sehen, wenn man in Hex schaut.)
Sie können die Funktion also wie folgt schreiben:
int ipToInt(int first,int second,int third,int fourth){return(first <<24)|(second <<16)|(third <<8)|(fourth);}
Ich glaube, dass IPs so spezifiziert wurden, um ein solches Verhalten spezifisch zu berücksichtigen ... Bitverschiebungen sind auf den meisten Mikroprozessoren viel effizienter als Mul und Adds.
Ape-inago
1
@ Ape-inago-Multiplikationen mit konstanten Zweierpotenzen werden normalerweise in Bitverschiebungen optimiert, fwiw.
Barry Kelly
Anstelle der Bitverschiebung können Sie die Reihenfolge, in der die Bytes gespeichert sind, verwenden LayoutKind.Explicitund FieldOffsetumkehren. Das funktioniert natürlich nur für die Little-Endian-Architektur. Beispiel auf Github .
RubberDuck
2
Haben Sie darauf hinweist , dass intso signiert ist , wenn Sie 192 um 24 Bits verschoben werden Sie negative ganze Zahl erhalten , also dieser Code für hohe Oktett mit hohem Bit an erster Stelle gebrochen.
Reverse()Gibt void zurück, sodass Sie es nicht aufrufen ToArray()können (für zukünftige Leser). Weisen Sie stattdessen den umgekehrten Bytes einen Wert zu, und rufen Sie ToArray () auf.
Erik Philips
1
Reverse () ist die Erweiterungsmethode von IEnumerable. Der obige Code ist vollkommen in Ordnung.
Ameise
3
Diese Methode liefert negative Zahlen für bestimmte IPs (z. B. 140.117.0.0)
lightxx
7
Da niemand den Code gepostet hat, der BitConverterdie Endianness verwendet und tatsächlich überprüft, geht es so weiter:
byte[] ip = address.Split('.').Select(s =>Byte.Parse(s)).ToArray();if(BitConverter.IsLittleEndian){Array.Reverse(ip);}int num =BitConverter.ToInt32(ip,0);
und zurück:
byte[] ip =BitConverter.GetBytes(num);if(BitConverter.IsLittleEndian){Array.Reverse(ip);}string address =String.Join(".", ip.Select(n => n.ToString()));
Sie müssen eine Uint verwenden, aber dies ist hier die richtigste Antwort.
RubberDuck
1
@RubberDuck: Sie müssen nur eine verwenden, uintwenn Sie die 32 Datenbits als vorzeichenlose Zahl möchten, intund kann dieselben Informationen speichern . Wenn Sie es in einer Datenbank speichern möchten und intbesser geeignet sind, benötigen Sie eine bigint, um es in der nicht signierten Form speichern zu können.
Guffa
1
Ein Uint ist eine bessere Darstellung IMO. Ein signiertes int benötigt etwas für das Zeichen, sodass Sie Adressen ganz oben im Bereich verlieren. Ja, es kann dieselben Daten enthalten, es wird jedoch als negative Zahl ausgegeben. Dies ist keine gültige IP, wenn Sie sie in die Adressleiste eingeben.
RubberDuck
@RubberDuck: In Form eines können uintSie es auch nicht in die Adressleiste eingeben , Sie müssen es zuerst in eine Textform konvertieren, um dies zu tun. Nur weil die Verwendung der einfachsten Form der Umwandlung eines intTextes keine funktionierende IP-Adresse erzeugt, ist dies kein gutes Argument dafür, sie nicht zu verwenden.
Guffa
@ RubberDuck: Das ist keine uint, das ist die Textdarstellung einer uint.
Guffa
7
Ich habe einige Probleme mit den beschriebenen Lösungen festgestellt, wenn ich IP-Adressen mit einem sehr großen Wert gegenüberstehe. Das Ergebnis wäre, dass das Byte [0] * 16777216-Ding überläuft und zu einem negativen int-Wert wird. Was es für mich behoben hat, ist die einfache Art des Gießvorgangs.
Meine Frage war geschlossen, ich habe keine Ahnung warum. Die akzeptierte Antwort hier ist nicht die gleiche wie das, was ich brauche.
Dies gibt mir den richtigen ganzzahligen Wert für eine IP.
publicdoubleIPAddressToNumber(stringIPaddress){int i;string[] arrDec;double num =0;if(IPaddress==""){return0;}else{
arrDec =IPaddress.Split('.');for(i = arrDec.Length-1; i >=0; i = i -1){
num +=((int.Parse(arrDec[i])%256)*Math.Pow(256,(3- i )));}return num;}}
Solange Sie die Konvertierung in beide Richtungen durchführen können, verstehe ich nicht, warum die Ausgabenummer korrekt sein muss, solange sie konsistent ist.
GateKiller
Hängt davon ab, wofür Sie die Nummer verwenden möchten. Sie können die andere Konvertierung nicht verwenden, um eine> = und <= Abfrage
durchzuführen
2
Mit dem UInt32 im richtigen Little-Endian-Format gibt es zwei einfache Konvertierungsfunktionen:
Mehrere der oben genannten Antworten wurden zu einer Erweiterungsmethode zusammengefasst, die die Endianness des Computers und IPv4-Adressen behandelt, die IPv6 zugeordnet wurden.
publicstaticclassIPAddressExtensions{/// <summary>/// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer./// </summary>/// <param name="address">The address to conver</param>/// <returns>An unsigned integer that represents an IPv4 address.</returns>publicstaticuintToUint(thisIPAddress address){if(address.AddressFamily==AddressFamily.InterNetwork|| address.IsIPv4MappedToIPv6){var bytes = address.GetAddressBytes();if(BitConverter.IsLittleEndian)Array.Reverse(bytes);returnBitConverter.ToUInt32(bytes,0);}thrownewArgumentOutOfRangeException("address","Address must be IPv4 or IPv4 mapped to IPv6");}}
Unit Tests:
[TestClass]publicclassIPAddressExtensionsTests{[TestMethod]publicvoidSimpleIp1(){var ip =IPAddress.Parse("0.0.0.15");uint expected =GetExpected(0,0,0,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidSimpleIp2(){var ip =IPAddress.Parse("0.0.1.15");uint expected =GetExpected(0,0,1,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidSimpleIpSix1(){var ip =IPAddress.Parse("0.0.0.15").MapToIPv6();uint expected =GetExpected(0,0,0,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidSimpleIpSix2(){var ip =IPAddress.Parse("0.0.1.15").MapToIPv6();uint expected =GetExpected(0,0,1,15);Assert.AreEqual(expected, ip.ToUint());}[TestMethod]publicvoidHighBits(){var ip =IPAddress.Parse("200.12.1.15").MapToIPv6();uint expected =GetExpected(200,12,1,15);Assert.AreEqual(expected, ip.ToUint());}uintGetExpected(uint a,uint b,uint c,uint d){return(a *256u*256u*256u)+(b *256u*256u)+(c *256u)+(d);}}
Ich denke, es wäre klarer, wenn Sie Shift anstelle von Math.Pow verwenden würden.
Mehrdad Afshari
Dies löst eine Überlaufausnahme aus, wenn zuerst> 127 lautet. Davy Landmans Antwort ist der beste Weg, dies zu tun.
Mhenry1384
int32 ist signiert und gibt einen negativen Wert> 127 für das erste Oktett zurück
Mateusz
1
publicboolTryParseIPv4Address(stringvalue,outuint result){IPAddress ipAddress;if(!IPAddress.TryParse(value,out ipAddress)||(ipAddress.AddressFamily!=System.Net.Sockets.AddressFamily.InterNetwork)){
result =0;returnfalse;}
result =BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(),0);returntrue;}
Das obige Beispiel wäre der Weg, den ich gehe. Möglicherweise müssen Sie nur zu Anzeigezwecken oder zu Zeichenfolgenzwecken in eine UInt32 konvertieren, einschließlich der Verwendung als lange Adresse in Zeichenfolgenform.
Welches ist, was benötigt wird, wenn die IPAddress.Parse (String) -Funktion verwendet wird. Seufzer.
Hier ist eine Lösung, die ich heute ausgearbeitet habe (hätte zuerst googeln sollen!):
privatestaticstringIpToDecimal2(string ipAddress){// need a shift counterint shift =3;// loop through the octets and compute the decimal versionvar octets = ipAddress.Split('.').Select(p =>long.Parse(p));return octets.Aggregate(0L,(total, octet)=>(total +(octet <<(shift--*8)))).ToString();}
Ich verwende LINQ, Lambda und einige der Erweiterungen für Generika. Während es das gleiche Ergebnis liefert, werden einige der neuen Sprachfunktionen verwendet, und Sie können dies in drei Codezeilen tun.
Ich habe die Erklärung auf meinem Blog, wenn Sie interessiert sind.
@ Dave Ladman Ihre Lösung mit Shift ist korrekt, aber nur für IP, die mit einer Zahl von weniger oder gleich 99 beginnen, muss der erste Oktekt tatsächlich zu lang sein.
Auf jeden Fall ist das Zurückkonvertieren mit langem Typ ziemlich schwierig, da 64 Bit (nicht 32 für Ip) gespeichert und 4 Bytes mit Nullen gefüllt werden
Die GetAddressBytes-Methode gibt die Bytes möglicherweise in umgekehrter Reihenfolge zurück, je nachdem, ob es sich bei der Maschine um Endian oder Endian handelt. Daher kann die richtige Anweisung für einige Maschinen lauten: long m_Address = (Adresse [0] << 24 | Adresse [1] << 16 | Adresse [2] << 8 | Adresse [3]) & 0x0FFFFFFFF
MiguelSlv
0
Ich habe festgestellt, dass System.Net.IPAddress über die Address-Eigenschaft (System.Int64) und den Konstruktor verfügt, die auch den Int64-Datentyp akzeptieren. Sie können dies also verwenden, um die IP-Adresse in das numerische Format (obwohl nicht Int32, sondern Int64) zu konvertieren.
int
s auf den meisten Systemen Little-Endian sind. Sie müssen also die Bytes vor dem Konvertieren umkehren. Siehe meine Antwort für korrekte Konvertierungen. Auch für IPv4int
können keine Adressen gespeichert werden127.255.255.255
, die größer als z. B. die Broadcast-Adresse sind. Verwenden Sie daher auint
.Antworten:
32-Bit-Ganzzahlen ohne Vorzeichen sind IPv4-Adressen. Während die
IPAddress.Address
Eigenschaft veraltet ist, ist sie eine Int64, die den vorzeichenlosen 32-Bit-Wert der IPv4-Adresse zurückgibt (der Haken ist, dass sie in der Reihenfolge der Netzwerkbytes vorliegt, sodass Sie sie austauschen müssen).Zum Beispiel ist meine lokale google.com bei
64.233.187.99
. Das entspricht:Und in der Tat, http: // 1089059683 / funktioniert wie erwartet (zumindest unter Windows, getestet mit IE, Firefox und Chrome; funktioniert jedoch nicht auf dem iPhone).
Hier ist ein Testprogramm, um beide Konvertierungen anzuzeigen, einschließlich des Austauschs von Netzwerk- / Host-Bytes:
quelle
Hier sind zwei Methoden zum Konvertieren von IPv4 in eine korrekte Ganzzahl und zurück:
Beispiel
Erläuterung
IP-Adressen sind in der Netzwerkreihenfolge (Big-Endian), während
int
s unter Windows Little-Endian sind. Um einen korrekten Wert zu erhalten, müssen Sie die Bytes umkehren, bevor Sie sie auf einem Little-Endian-System konvertieren.Auch selbst für
IPv4
eineint
nicht halten können Adressen größer als127.255.255.255
zB die Broadcast - Adresse(255.255.255.255)
, so verwendet einuint
.quelle
1.1.1.1
weil sein Byte-Array palindromisch ist. Versuchen Sie es mit nicht palindromischen wie127.0.0.1
oder192.168.1.1
.1.1.1.1
,2.2.2.2
,123.123.123.123
ergeben immer das gleiche Ergebnis. Für die Nachwelt siehe aktualisierte Geige: dotnetfiddle.net/aR6fhcSystem.Net.IPAddress
, um dies zum Laufen zu bringen. Funktioniert super!2.1.1.2
wäre auch so.@Barry Kelly und @Andrew Hare, eigentlich denke ich nicht, dass Multiplikation der klarste Weg ist, dies zu tun (obwohl richtig).
Eine Int32 "formatierte" IP-Adresse kann als die folgende Struktur angesehen werden
Um die IP-Adresse 64.233.187.99 zu konvertieren, können Sie Folgendes tun:
Sie können sie also mit + addieren oder binairy oder sie zusammen verwenden. Das Ergebnis ist 0x40E9BB63 (1089059683). (Meiner Meinung nach ist es viel einfacher, die Bytes zu sehen, wenn man in Hex schaut.)
Sie können die Funktion also wie folgt schreiben:
quelle
LayoutKind.Explicit
undFieldOffset
umkehren. Das funktioniert natürlich nur für die Little-Endian-Architektur. Beispiel auf Github .int
so signiert ist , wenn Sie 192 um 24 Bits verschoben werden Sie negative ganze Zahl erhalten , also dieser Code für hohe Oktett mit hohem Bit an erster Stelle gebrochen.Probieren Sie diese aus:
quelle
Reverse()
Gibt void zurück, sodass Sie es nicht aufrufenToArray()
können (für zukünftige Leser). Weisen Sie stattdessen den umgekehrten Bytes einen Wert zu, und rufen Sie ToArray () auf.IEnumerable
. Der obige Code ist vollkommen in Ordnung.Da niemand den Code gepostet hat, der
BitConverter
die Endianness verwendet und tatsächlich überprüft, geht es so weiter:und zurück:
quelle
uint
wenn Sie die 32 Datenbits als vorzeichenlose Zahl möchten,int
und kann dieselben Informationen speichern . Wenn Sie es in einer Datenbank speichern möchten undint
besser geeignet sind, benötigen Sie einebigint
, um es in der nicht signierten Form speichern zu können.uint
Sie es auch nicht in die Adressleiste eingeben , Sie müssen es zuerst in eine Textform konvertieren, um dies zu tun. Nur weil die Verwendung der einfachsten Form der Umwandlung einesint
Textes keine funktionierende IP-Adresse erzeugt, ist dies kein gutes Argument dafür, sie nicht zu verwenden.uint
, das ist die Textdarstellung eineruint
.Ich habe einige Probleme mit den beschriebenen Lösungen festgestellt, wenn ich IP-Adressen mit einem sehr großen Wert gegenüberstehe. Das Ergebnis wäre, dass das Byte [0] * 16777216-Ding überläuft und zu einem negativen int-Wert wird. Was es für mich behoben hat, ist die einfache Art des Gießvorgangs.
quelle
Die Umkehrung von Davy Landmans Funktion
quelle
Meine Frage war geschlossen, ich habe keine Ahnung warum. Die akzeptierte Antwort hier ist nicht die gleiche wie das, was ich brauche.
Dies gibt mir den richtigen ganzzahligen Wert für eine IP.
quelle
Mit dem UInt32 im richtigen Little-Endian-Format gibt es zwei einfache Konvertierungsfunktionen:
quelle
Mehrere der oben genannten Antworten wurden zu einer Erweiterungsmethode zusammengefasst, die die Endianness des Computers und IPv4-Adressen behandelt, die IPv6 zugeordnet wurden.
Unit Tests:
quelle
Wenn Sie an der Funktion interessiert waren, lautet die Antwort hier nicht nur:
mit
first
durchfourth
sind die Segmente der IPv4-Adresse.quelle
quelle
Das obige Beispiel wäre der Weg, den ich gehe. Möglicherweise müssen Sie nur zu Anzeigezwecken oder zu Zeichenfolgenzwecken in eine UInt32 konvertieren, einschließlich der Verwendung als lange Adresse in Zeichenfolgenform.
Welches ist, was benötigt wird, wenn die IPAddress.Parse (String) -Funktion verwendet wird. Seufzer.
quelle
Hier ist eine Lösung, die ich heute ausgearbeitet habe (hätte zuerst googeln sollen!):
Ich verwende LINQ, Lambda und einige der Erweiterungen für Generika. Während es das gleiche Ergebnis liefert, werden einige der neuen Sprachfunktionen verwendet, und Sie können dies in drei Codezeilen tun.
Ich habe die Erklärung auf meinem Blog, wenn Sie interessiert sind.
Prost, -jc
quelle
Ich denke, das ist falsch: "65536" ==> 0.0.255.255 "Sollte sein:" 65535 "==> 0.0.255.255" oder "65536" ==> 0.1.0.0 "
quelle
@ Dave Ladman Ihre Lösung mit Shift ist korrekt, aber nur für IP, die mit einer Zahl von weniger oder gleich 99 beginnen, muss der erste Oktekt tatsächlich zu lang sein.
Auf jeden Fall ist das Zurückkonvertieren mit langem Typ ziemlich schwierig, da 64 Bit (nicht 32 für Ip) gespeichert und 4 Bytes mit Nullen gefüllt werden
Genießen!
Massimo
quelle
Angenommen, Sie haben eine IP-Adresse im Zeichenfolgenformat (z. B. 254.254.254.254).
quelle
Ausgabe: 10101005056
quelle
quelle
Ich habe festgestellt, dass System.Net.IPAddress über die Address-Eigenschaft (System.Int64) und den Konstruktor verfügt, die auch den Int64-Datentyp akzeptieren. Sie können dies also verwenden, um die IP-Adresse in das numerische Format (obwohl nicht Int32, sondern Int64) zu konvertieren.
quelle
Schauen Sie sich einige der verrückten Parsing-Beispiele in .Nets IPAddress.Parse an: ( MSDN )
65536 ==> 0.0.255.255
20.2 ==> 20.0.0.2
20.65535 ==> 20.0.255.255
128.1.2 ==> 128.1.0.2
quelle