Como converter um endereço IPv4 em um inteiro em c #?

Eu estou procurando uma function que irá converter um endereço IPv4 padrão em um Integer. Pontos de bônus disponíveis para uma function que fará o oposto.

Solução deve estar em C #.

Inteiros não assinados de 32 bits são endereços IPv4. Enquanto isso, a propriedade IPAddress.Address , embora preterida, é uma Int64 que retorna o valor não assinado de 32 bits do endereço IPv4 (a captura é, está na ordem de bytes da rede, portanto é necessário trocá-lo).

Por exemplo, o meu google.com local está em 64.233.187.99 . Isso é equivalente a:

 64*2^24 + 233*2^16 + 187*2^8 + 99 = 1089059683 

E, de fato, o http: // 1089059683 / funciona como esperado (pelo menos no Windows, testado com o IE, Firefox e Chrome; não funciona no iPhone).

Aqui está um programa de teste para mostrar as duas conversões, incluindo a troca de bytes de rede / host:

 using System; using System.Net; class App { static long ToInt(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); } static string ToAddr(long address) { return IPAddress.Parse(address.ToString()).ToString(); // This also works: // return new IPAddress((uint) IPAddress.HostToNetworkOrder( // (int) address)).ToString(); } static void Main() { Console.WriteLine(ToInt("64.233.187.99")); Console.WriteLine(ToAddr(1089059683)); } } 

@Barry Kelly e @Andrew Hare, na verdade, eu não acho que multiplicar seja a maneira mais clara de fazer isso (tudo correto).

Um endereço IP Int32 “formatado” pode ser visto como a seguinte estrutura

 [StructLayout(LayoutKind.Sequential, Pack = 1)] struct IPv4Address { public Byte A; public Byte B; public Byte C; public Byte D; } // to actually cast it from or to an int32 I think you // need to reverse the fields due to little endian 

Então, para converter o endereço IP 64.233.187.99 você poderia fazer:

 (64 = 0x40) << 24 == 0x40000000 (233 = 0xE9) << 16 == 0x00E90000 (187 = 0xBB) << 8 == 0x0000BB00 (99 = 0x63) == 0x00000063 ---------- =| 0x40E9BB63 

então você poderia adicioná-los usando + ou você poderia binairy ou eles juntos. Resultando em 0x40E9BB63 que é 1089059683. (Na minha opinião, olhando em hexadecimal é muito mais fácil ver os bytes)

Então você poderia escrever a function como:

 int ipToInt(int first, int second, int third, int fourth) { return (first << 24) | (second << 16) | (third << 8) | (fourth); } 

Para converter de IPv4 para inteiro correto:

 IPAddress address = IPAddress.Parse("255.255.255.255"); byte[] bytes = address.GetAddressBytes(); Array.Reverse(bytes); // flip big-endian(network order) to little-endian uint intAddress = BitConverter.ToUInt32(bytes, 0); 

E para converter de volta:

 byte[] bytes = BitConverter.GetBytes(4294967295); Array.Reverse(bytes); // flip little-endian to big-endian(network order) string ipAddress = new IPAddress(bytes).ToString(); 

Explicação:

Endereços IP estão em ordem de rede (big-endian), enquanto int s são little-endian no Windows, portanto, para obter um valor correto, você deve inverter os bytes antes de converter.

Além disso, mesmo para o IPv4 , um int não pode conter endereços maiores que 127.255.255.255 , por exemplo, o endereço de broadcast (255.255.255.255) , então use um uint .

Tente isto:

 private int IpToInt32(string ipAddress) { return BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray(), 0); } private string Int32ToIp(int ipAddress) { return new IPAddress(BitConverter.GetBytes(ipAddress).Reverse().ToArray()).ToString(); } 

Como ninguém postou o código que usa BitConverter e realmente verifica o endianness, aqui vai:

 byte[] ip = address.Split('.').Select(s => Byte.Parse(s)).ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(ip); } int num = BitConverter.ToInt32(ip, 0); 

e volta:

 byte[] ip = BitConverter.GetBytes(num); if (BitConverter.IsLittleEndian) { Array.Reverse(ip); } string address = String.Join(".", ip.Select(n => n.ToString())); 

Eu encontrei alguns problemas com as soluções descritas, ao enfrentar IP Adresses com um valor muito grande. O resultado seria, que a coisa byte [0] * 16777216 transbordaria e se tornaria um valor int negativo. o que consertou para mim, é a operação de fundição de tipo simples.

 public static long ConvertIPToLong(string ipAddress) { System.Net.IPAddress ip; if (System.Net.IPAddress.TryParse(ipAddress, out ip)) { byte[] bytes = ip.GetAddressBytes(); return (long) ( 16777216 * (long)bytes[0] + 65536 * (long)bytes[1] + 256 * (long)bytes[2] + (long)bytes[3] ) ; } else return 0; } 

Minha pergunta foi encerrada, não tenho idéia do porquê. A resposta aceita aqui não é a mesma que eu preciso.

Isso me dá o valor inteiro correto para um IP ..

 public double IPAddressToNumber(string IPaddress) { int i; string [] arrDec; double num = 0; if (IPaddress == "") { return 0; } 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; } } 

O reverso da function de Davy Landman

 string IntToIp(int d) { int v1 = d & 0xff; int v2 = (d >> 8) & 0xff; int v3 = (d >> 16) & 0xff; int v4 = (d >> 24); return v4 + "." + v3 + "." + v2 + "." + v1; } 

Se você estava interessado na function, não apenas a resposta aqui é como é feita:

 int ipToInt(int first, int second, int third, int fourth) { return Convert.ToInt32((first * Math.Pow(256, 3)) + (second * Math.Pow(256, 2)) + (third * 256) + fourth); } 

de first a fourth são os segmentos do endereço IPv4.

Com o UInt32 no formato little-endian adequado, aqui estão duas funções de conversão simples:

 public uint GetIpAsUInt32(string ipString) { IPAddress address = IPAddress.Parse(ipString); byte[] ipBytes = address.GetAddressBytes(); Array.Reverse(ipBytes); return BitConverter.ToUInt32(ipBytes, 0); } public string GetIpAsString(uint ipVal) { byte[] ipBytes = BitConverter.GetBytes(ipVal); Array.Reverse(ipBytes); return new IPAddress(ipBytes).ToString(); } 
 public bool TryParseIPv4Address(string value, out uint result) { IPAddress ipAddress; if (!IPAddress.TryParse(value, out ipAddress) || (ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)) { result = 0; return false; } result = BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(), 0); return true; } 
  public static Int32 getLongIPAddress(string ipAddress) { return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0)); } 

O exemplo acima seria o caminho que eu vou … A única coisa que você pode ter que fazer é converter para um UInt32 para fins de exibição, ou propósitos de string, incluindo usá-lo como um endereço longo em forma de string.

Qual é o necessário ao usar a function IPAddress.Parse (String). Suspiro.

Reuniu várias das respostas acima em um método de extensão que manipula o Endianness da máquina e lida com endereços IPv4 que foram mapeados para o IPv6.

 public static class IPAddressExtensions { ///  /// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer. ///  /// The address to conver /// An unsigned integer that represents an IPv4 address. public static uint ToUint(this IPAddress address) { if (address.AddressFamily == AddressFamily.InterNetwork || address.IsIPv4MappedToIPv6) { var bytes = address.GetAddressBytes(); if (BitConverter.IsLittleEndian) Array.Reverse(bytes); return BitConverter.ToUInt32(bytes, 0); } throw new ArgumentOutOfRangeException("address", "Address must be IPv4 or IPv4 mapped to IPv6"); } } 

Testes unitários:

 [TestClass] public class IPAddressExtensionsTests { [TestMethod] public void SimpleIp1() { var ip = IPAddress.Parse("0.0.0.15"); uint expected = GetExpected(0, 0, 0, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void SimpleIp2() { var ip = IPAddress.Parse("0.0.1.15"); uint expected = GetExpected(0, 0, 1, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void SimpleIpSix1() { var ip = IPAddress.Parse("0.0.0.15").MapToIPv6(); uint expected = GetExpected(0, 0, 0, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void SimpleIpSix2() { var ip = IPAddress.Parse("0.0.1.15").MapToIPv6(); uint expected = GetExpected(0, 0, 1, 15); Assert.AreEqual(expected, ip.ToUint()); } [TestMethod] public void HighBits() { var ip = IPAddress.Parse("200.12.1.15").MapToIPv6(); uint expected = GetExpected(200, 12, 1, 15); Assert.AreEqual(expected, ip.ToUint()); } uint GetExpected(uint a, uint b, uint c, uint d) { return (a * 256u * 256u * 256u) + (b * 256u * 256u) + (c * 256u) + (d); } } 

aqui está uma solução que eu trabalhei hoje (deveria ter pesquisado primeiro!):

  private static string IpToDecimal2(string ipAddress) { // need a shift counter int shift = 3; // loop through the octets and compute the decimal version var octets = ipAddress.Split('.').Select(p => long.Parse(p)); return octets.Aggregate(0L, (total, octet) => (total + (octet << (shift-- * 8)))).ToString(); } 

Eu estou usando o LINQ, lambda e algumas das extensões em genéricos, então enquanto ele produz o mesmo resultado, ele usa alguns dos novos resources de linguagem e você pode fazer isso em três linhas de código.

Eu tenho a explicação no meu blog se você estiver interessado.

felicidades, -jc

Eu acho que isso está errado: “65536” ==> 0.0.255.255 “deve ser:” 65535 “==> 0.0.255.255” ou “65536” ==> 0.1.0.0 ”

@Davy Ladman sua solução com shift é corrent mas somente para ip começando com number menor ou igual a 99, na primeira octeto deve ser convertido para long.

De qualquer forma converter de volta com o tipo longo é muito difícil porque armazenar 64 bits (não 32 para Ip) e preencher 4 bytes com zeros

 static uint ToInt(string addr) { return BitConverter.ToUInt32(IPAddress.Parse(addr).GetAddressBytes(), 0); } static string ToAddr(uint address) { return new IPAddress(address).ToString(); } 

Apreciar!

Massimo

Supondo que você tenha um endereço IP no formato de string (por exemplo, 254.254.254.254)

 string[] vals = inVal.Split('.'); uint output = 0; for (byte i = 0; i < vals.Length; i++) output += (uint)(byte.Parse(vals[i]) << 8 * (vals.GetUpperBound(0) - i)); 
 var ipAddress = "10.101.5.56"; var longAddress = long.Parse(string.Join("", ipAddress.Split('.').Select(x => x.PadLeft(3, '0')))); Console.WriteLine(longAddress); 

Produção: 10101005056

 var address = IPAddress.Parse("10.0.11.174").GetAddressBytes(); long m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF); 

Dê uma olhada em alguns dos exemplos de análise malucos em IPAddress.Parse do .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