ATTENTION : les entiers résultant de la réponse acceptée seront faux , car les adresses IP sont dans l'ordre du réseau (big-endian), tandis que ints sont little-endian sur la plupart des systèmes. Vous devez donc inverser les octets avant de convertir. Voir ma réponse pour les conversions correctes. De plus, même pour IPv4, un intne peut pas contenir d'adresses plus grandes que 127.255.255.255, par exemple, l'adresse de diffusion, alors utilisez un uint.
Saeb Amini
Réponses:
137
Les entiers non signés 32 bits sont des adresses IPv4. Pendant ce temps, la IPAddress.Addresspropriété, bien que déconseillée, est un Int64 qui renvoie la valeur 32 bits non signée de l'adresse IPv4 (le hic, c'est qu'elle est dans l'ordre des octets du réseau, vous devez donc l'échanger).
Par exemple, mon google.com local est à 64.233.187.99. C'est équivalent à:
64*2^24+233*2^16+187*2^8+99=1089059683
Et en effet, http: // 1089059683 / fonctionne comme prévu (au moins sous Windows, testé avec IE, Firefox et Chrome; ne fonctionne pas sur iPhone cependant).
Voici un programme de test pour afficher les deux conversions, y compris l'échange d'octets réseau / hôte:
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));}}
Confirmé dans Opera 11 sur Ubuntu Linux 10.04: il reconvertit l'int en une forme familière de wxyz, et ça marche.
Piskvor a quitté le bâtiment
6
IPAddress.Address est obsolète depuis .Net 4.0.
Erik Philips
@ErikPhilips Est-ce important si vous utilisez uniquement IPv4?
Ray
C'est une décision architecturale. Il a ses avantages et ses inconvénients et les commentaires ne sont pas le meilleur endroit pour discuter de cette question spécifique.
Erik Philips
1
vous pouvez utiliser BitConverter.ToUInt32 (IPAddress.Parse (value) .GetAddressBytes (). Reverse (). ToArray () pour corriger IPAddress.Address est obsolète
Mhmd
43
Voici une paire de méthodes pour convertir IPv4 en un entier correct et inversement:
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();}
Les adresses IP sont dans l'ordre du réseau (big-endian), tandis que ints sont little-endian sous Windows, donc pour obtenir une valeur correcte, vous devez inverser les octets avant de convertir sur un système little-endian.
De plus, même pour IPv4, an intne peut pas contenir d'adresses plus grandes que 127.255.255.255, par exemple, l'adresse de diffusion (255.255.255.255), alors utilisez un uint.
Cela ne semble pas réellement faire de différence sur Windows utilisant .NET - je ne suis pas sûr de Mono. Voir dotnetfiddle.net/cBIOj2
Jesse
2
@Jesse cela ne fait pas de différence pour votre entrée 1.1.1.1car son tableau d'octets est palindromique. Essayez avec des non-palindromiques comme 127.0.0.1ou 192.168.1.1.
Saeb Amini
Je vois le problème. Numéros répétés tels que 1.1.1.1, 2.2.2.2, 123.123.123.123donnent toujours le même résultat. Pour la postérité, voir le violon mis à jour: dotnetfiddle.net/aR6fhc
Jesse
Je tiens à noter que je devais utiliser System.Net.IPAddresspour que cela fonctionne. Fonctionne très bien!
Shrout1
1
@Jesse ce ne serait pas seulement pour répéter des nombres, mais pour toutes les adresses IP palindromiques . Ce 2.1.1.2serait pareil.
Saeb Amini
40
@Barry Kelly et @Andrew Hare, en fait, je ne pense pas que multiplier soit le moyen le plus clair de le faire (tout est correct).
Une adresse IP "formatée" Int32 peut être considérée comme la structure suivante
[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
Donc, pour convertir l'adresse IP 64.233.187.99, vous pouvez faire:
vous pouvez donc les additionner en utilisant + ou vous pouvez binairy ou les ensemble. Résultat 0x40E9BB63 qui est 1089059683. (À mon avis, en regardant en hexadécimal, il est beaucoup plus facile de voir les octets)
Vous pouvez donc écrire la fonction comme suit:
int ipToInt(int first,int second,int third,int fourth){return(first <<24)|(second <<16)|(third <<8)|(fourth);}
Je crois que les ip ont été spécifiés de cette façon pour permettre spécifiquement un tel comportement ... les décalages de bits sont beaucoup plus efficaces sur la plupart des microprocesseurs que les muls et les ajouts.
Ape-inago le
1
@ Les multiplications Ape-inago par des puissances constantes de deux sont normalement optimisées en décalages de bits, fwiw.
Barry Kelly
Au lieu du décalage de bits, vous pouvez utiliser LayoutKind.Explicitet FieldOffsetpour inverser l'ordre dans lequel les octets sont stockés. Bien sûr, cela ne fonctionne que pour l'architecture little endian. Exemple sur github .
RubberDuck
2
Je dois souligner que intc'est signé, donc si vous décalez 192 de 24 bits, vous obtiendrez un entier négatif, donc ce code est cassé pour l'octet haut ayant le bit haut à la première place.
Reverse()renvoie void, vous ne pouvez donc pas y faire appel ToArray()(pour les futurs lecteurs). Au lieu de cela, attribuez une valeur aux octets inversés, puis vous pouvez appeler ToArray ().
Erik Philips
1
Reverse () est la méthode d'extension de IEnumerable. Le code ci-dessus est parfaitement correct.
Ant
3
Cette méthode donne des nombres négatifs pour certaines adresses IP (par exemple, 140.117.0.0)
lightxx
7
Comme personne n'a posté le code qui utilise BitConverteret vérifie réellement l'endianness, voici:
byte[] ip = address.Split('.').Select(s =>Byte.Parse(s)).ToArray();if(BitConverter.IsLittleEndian){Array.Reverse(ip);}int num =BitConverter.ToInt32(ip,0);
et retour:
byte[] ip =BitConverter.GetBytes(num);if(BitConverter.IsLittleEndian){Array.Reverse(ip);}string address =String.Join(".", ip.Select(n => n.ToString()));
Vous devez utiliser un uint, mais c'est la réponse la plus correcte ici.
RubberDuck
1
@RubberDuck: Vous devez uniquement utiliser un uintsi vous voulez que les 32 bits de données intsoient un nombre non signé, un est capable de contenir les mêmes informations. Si vous souhaitez le stocker dans une base de données intmieux adaptée, vous avez besoin d'un bigintpour pouvoir le stocker sous la forme non signée.
Guffa
1
Un uint est une meilleure représentation de l'OMI. Un int signé a besoin d'un peu pour le signe, vous perdez donc des adresses tout en haut de gamme. Oui, il peut contenir les mêmes données, mais il sera affiché sous la forme d'un nombre négatif, qui n'est pas une adresse IP valide si vous le saisissez dans la barre d'adresse.
RubberDuck
@RubberDuck: Sous la forme d'un, uintvous ne pouvez pas non plus le taper dans la barre d'adresse, vous devez d'abord le convertir en texte pour ce faire. Le simple fait d'utiliser la forme la plus simple de transformation d'un inttexte en texte ne produit pas d'adresse IP fonctionnelle n'est pas un bon argument pour ne pas l'utiliser.
Guffa
@RubberDuck: Ce n'est pas un uint, c'est la représentation textuelle d'un uint.
Guffa
7
J'ai rencontré des problèmes avec les solutions décrites, face à des adresses IP avec une très grande valeur. Le résultat serait que l'octet [0] * 16777216 thingy déborderait et deviendrait une valeur int négative. ce qui l'a résolu pour moi, c'est une opération de moulage de type simple.
Ma question était close, je ne sais pas pourquoi. La réponse acceptée ici n'est pas la même que ce dont j'ai besoin.
Cela me donne la valeur entière correcte pour une adresse 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;}}
Tant que vous pouvez effectuer la conversion dans les deux sens, je ne vois pas pourquoi le numéro de sortie doit être correct tant qu'il est cohérent.
GateKiller
Dépend de ce pour quoi vous souhaitez utiliser le numéro. Vous ne pouvez pas utiliser l'autre conversion pour faire une requête> = et <= pour trouver une adresse IP ..
Coolcoder
2
Avec l'UInt32 dans le bon format petit-boutiste, voici deux fonctions de conversion simples:
Assemblage de plusieurs des réponses ci-dessus dans une méthode d'extension qui gère l'endianness de la machine et gère les adresses IPv4 qui ont été mappées à IPv6.
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");}}
Tests unitaires:
[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);}}
Je pense que ce serait plus clair si vous aviez utilisé shift au lieu de Math.Pow.
Mehrdad Afshari
Cela lèvera une exception de débordement si first est> 127. La réponse de Davy Landman est la meilleure façon de le faire.
mhenry1384
int32 est signé donc il retournera une valeur négative> 127 pour le premier octet
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;}
L'exemple ci-dessus serait la façon dont je vais .. La seule chose que vous pourriez avoir à faire est de convertir en UInt32 à des fins d'affichage, ou à des fins de chaîne, y compris en l'utilisant comme une longue adresse sous forme de chaîne.
C'est ce qui est nécessaire lors de l'utilisation de la fonction IPAddress.Parse (String). Soupir.
voici une solution que j'ai élaborée aujourd'hui (j'aurais dû googler d'abord!):
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();}
J'utilise LINQ, lambda et certaines des extensions sur les génériques, donc bien qu'il produise le même résultat, il utilise certaines des nouvelles fonctionnalités du langage et vous pouvez le faire en trois lignes de code.
j'ai l'explication sur mon blog si vous êtes intéressé.
@Davy Ladman votre solution avec shift est correcte mais seulement pour ip commençant par un nombre inférieur ou égal à 99, en fait le premier octect doit être converti en long.
Quoi qu'il en soit, la reconversion avec le type long est assez difficile car stocker 64 bits (pas 32 pour Ip) et remplir 4 octets avec des zéros
la méthode GetAddressBytes peut renvoyer les octets dans l'ordre inverse, selon que la machine est endian ou endian-ness donc l'instruction correcte peut être pour certaines machines: long m_Address = (address [0] << 24 | address [1] << 16 | adresse [2] << 8 | adresse [3]) & 0x0FFFFFFFF
MiguelSlv
0
J'ai remarqué que System.Net.IPAddress a la propriété Address (System.Int64) et le constructeur, qui acceptent également le type de données Int64. Vous pouvez donc l'utiliser pour convertir l'adresse IP vers / depuis le format numérique (mais pas Int32, mais Int64).
int
s sont little-endian sur la plupart des systèmes. Vous devez donc inverser les octets avant de convertir. Voir ma réponse pour les conversions correctes. De plus, même pour IPv4, unint
ne peut pas contenir d'adresses plus grandes que127.255.255.255
, par exemple, l'adresse de diffusion, alors utilisez unuint
.Réponses:
Les entiers non signés 32 bits sont des adresses IPv4. Pendant ce temps, la
IPAddress.Address
propriété, bien que déconseillée, est un Int64 qui renvoie la valeur 32 bits non signée de l'adresse IPv4 (le hic, c'est qu'elle est dans l'ordre des octets du réseau, vous devez donc l'échanger).Par exemple, mon google.com local est à
64.233.187.99
. C'est équivalent à:Et en effet, http: // 1089059683 / fonctionne comme prévu (au moins sous Windows, testé avec IE, Firefox et Chrome; ne fonctionne pas sur iPhone cependant).
Voici un programme de test pour afficher les deux conversions, y compris l'échange d'octets réseau / hôte:
la source
Voici une paire de méthodes pour convertir IPv4 en un entier correct et inversement:
Exemple
Explication
Les adresses IP sont dans l'ordre du réseau (big-endian), tandis que
int
s sont little-endian sous Windows, donc pour obtenir une valeur correcte, vous devez inverser les octets avant de convertir sur un système little-endian.De plus, même pour
IPv4
, anint
ne peut pas contenir d'adresses plus grandes que127.255.255.255
, par exemple, l'adresse de diffusion(255.255.255.255)
, alors utilisez unuint
.la source
1.1.1.1
car son tableau d'octets est palindromique. Essayez avec des non-palindromiques comme127.0.0.1
ou192.168.1.1
.1.1.1.1
,2.2.2.2
,123.123.123.123
donnent toujours le même résultat. Pour la postérité, voir le violon mis à jour: dotnetfiddle.net/aR6fhcSystem.Net.IPAddress
pour que cela fonctionne. Fonctionne très bien!2.1.1.2
serait pareil.@Barry Kelly et @Andrew Hare, en fait, je ne pense pas que multiplier soit le moyen le plus clair de le faire (tout est correct).
Une adresse IP "formatée" Int32 peut être considérée comme la structure suivante
Donc, pour convertir l'adresse IP 64.233.187.99, vous pouvez faire:
vous pouvez donc les additionner en utilisant + ou vous pouvez binairy ou les ensemble. Résultat 0x40E9BB63 qui est 1089059683. (À mon avis, en regardant en hexadécimal, il est beaucoup plus facile de voir les octets)
Vous pouvez donc écrire la fonction comme suit:
la source
LayoutKind.Explicit
etFieldOffset
pour inverser l'ordre dans lequel les octets sont stockés. Bien sûr, cela ne fonctionne que pour l'architecture little endian. Exemple sur github .int
c'est signé, donc si vous décalez 192 de 24 bits, vous obtiendrez un entier négatif, donc ce code est cassé pour l'octet haut ayant le bit haut à la première place.Essayez ceux-ci:
la source
Reverse()
renvoie void, vous ne pouvez donc pas y faire appelToArray()
(pour les futurs lecteurs). Au lieu de cela, attribuez une valeur aux octets inversés, puis vous pouvez appeler ToArray ().IEnumerable
. Le code ci-dessus est parfaitement correct.Comme personne n'a posté le code qui utilise
BitConverter
et vérifie réellement l'endianness, voici:et retour:
la source
uint
si vous voulez que les 32 bits de donnéesint
soient un nombre non signé, un est capable de contenir les mêmes informations. Si vous souhaitez le stocker dans une base de donnéesint
mieux adaptée, vous avez besoin d'unbigint
pour pouvoir le stocker sous la forme non signée.uint
vous ne pouvez pas non plus le taper dans la barre d'adresse, vous devez d'abord le convertir en texte pour ce faire. Le simple fait d'utiliser la forme la plus simple de transformation d'unint
texte en texte ne produit pas d'adresse IP fonctionnelle n'est pas un bon argument pour ne pas l'utiliser.uint
, c'est la représentation textuelle d'unuint
.J'ai rencontré des problèmes avec les solutions décrites, face à des adresses IP avec une très grande valeur. Le résultat serait que l'octet [0] * 16777216 thingy déborderait et deviendrait une valeur int négative. ce qui l'a résolu pour moi, c'est une opération de moulage de type simple.
la source
L'inverse de la fonction de Davy Landman
la source
Ma question était close, je ne sais pas pourquoi. La réponse acceptée ici n'est pas la même que ce dont j'ai besoin.
Cela me donne la valeur entière correcte pour une adresse IP.
la source
Avec l'UInt32 dans le bon format petit-boutiste, voici deux fonctions de conversion simples:
la source
Assemblage de plusieurs des réponses ci-dessus dans une méthode d'extension qui gère l'endianness de la machine et gère les adresses IPv4 qui ont été mappées à IPv6.
Tests unitaires:
la source
Si vous étiez intéressé par la fonction, pas seulement la réponse, voici comment cela se fait:
avec à
first
traversfourth
les segments de l'adresse IPv4.la source
la source
L'exemple ci-dessus serait la façon dont je vais .. La seule chose que vous pourriez avoir à faire est de convertir en UInt32 à des fins d'affichage, ou à des fins de chaîne, y compris en l'utilisant comme une longue adresse sous forme de chaîne.
C'est ce qui est nécessaire lors de l'utilisation de la fonction IPAddress.Parse (String). Soupir.
la source
voici une solution que j'ai élaborée aujourd'hui (j'aurais dû googler d'abord!):
J'utilise LINQ, lambda et certaines des extensions sur les génériques, donc bien qu'il produise le même résultat, il utilise certaines des nouvelles fonctionnalités du langage et vous pouvez le faire en trois lignes de code.
j'ai l'explication sur mon blog si vous êtes intéressé.
bravo, -jc
la source
Je pense que c'est faux: "65536" ==> 0.0.255.255 "Devrait être:" 65535 "==> 0.0.255.255" ou "65536" ==> 0.1.0.0 "
la source
@Davy Ladman votre solution avec shift est correcte mais seulement pour ip commençant par un nombre inférieur ou égal à 99, en fait le premier octect doit être converti en long.
Quoi qu'il en soit, la reconversion avec le type long est assez difficile car stocker 64 bits (pas 32 pour Ip) et remplir 4 octets avec des zéros
Prendre plaisir!
Massimo
la source
En supposant que vous ayez une adresse IP au format chaîne (par exemple 254.254.254.254)
la source
Sortie: 10101005056
la source
la source
J'ai remarqué que System.Net.IPAddress a la propriété Address (System.Int64) et le constructeur, qui acceptent également le type de données Int64. Vous pouvez donc l'utiliser pour convertir l'adresse IP vers / depuis le format numérique (mais pas Int32, mais Int64).
la source
Jetez un œil à certains des exemples d'analyse fous dans IPAddress.Parse de .Net: ( 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
la source