32位无符号整数是IPv4地址。同时,虽然已被弃用,但IPAddress.Address
属性是一个Int64,返回IPv4地址的无符号32位值(关键是,它以网络字节顺序提供,所以您需要交换它)。
例如,我的本地google.com在64.233.187.99
。这相当于:
64*2^24 + 233*2^16 + 187*2^8 + 99
= 1089059683
的确,http://1089059683/按预期工作(至少在Windows上测试过,使用IE、Firefox和Chrome;但在iPhone上无法使用)。
以下是用于显示转换的测试程序,包括网络/主机字节交换:
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));
}
}
ulong
。 - Mason.Chase以下是一对将IPv4地址转换为正确整数以及将整数转换回IPv4地址的方法:
public static uint ConvertFromIpAddressToInteger(string ipAddress)
{
var address = IPAddress.Parse(ipAddress);
byte[] bytes = address.GetAddressBytes();
// flip big-endian(network order) to little-endian
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return BitConverter.ToUInt32(bytes, 0);
}
public static string ConvertFromIntegerToIpAddress(uint ipAddress)
{
byte[] bytes = BitConverter.GetBytes(ipAddress);
// flip little-endian to big-endian(network order)
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return new IPAddress(bytes).ToString();
}
示例
ConvertFromIpAddressToInteger("255.255.255.254"); // 4294967294
ConvertFromIntegerToIpAddress(4294967294); // 255.255.255.254
说明
IP地址采用网络字节序(大端序)表示,而在Windows中int
使用的是小端序,因此在小端序系统上进行转换前必须先反转字节顺序以得到正确的值。
同时,即使是对于IPv4
地址,int
也无法容纳大于127.255.255.255
的地址(例如广播地址(255.255.255.255)
),因此请使用uint
。
1.1.1.1
来说,这并没有什么区别,因为它的字节数组是回文的。试试非回文的IP地址,比如127.0.0.1
或192.168.1.1
。 - Saeb Amini1.1.1.1
、2.2.2.2
、123.123.123.123
总是产生相同的结果。为了记录,请查看更新后的fiddle链接:https://dotnetfiddle.net/aR6fhc - JesseSystem.Net.IPAddress
才能使其正常工作。效果很好! - Shrout1@Barry Kelly和@Andrew Hare,实际上我认为乘法并不是最清晰的方式来做到这一点(虽然正确)。
一个Int32的“格式化”IP地址可以被视为以下结构
[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
如果要将 IP 地址 64.233.187.99 转换为十六进制,可以这样做:
(64 = 0x40) << 24 == 0x40000000
(233 = 0xE9) << 16 == 0x00E90000
(187 = 0xBB) << 8 == 0x0000BB00
(99 = 0x63) == 0x00000063
---------- =|
0x40E9BB63
你可以使用加号将它们相加,也可以将它们二进制或在一起。结果为0x40E9BB63,即1089059683。(个人认为,在十六进制下查看字节更容易一些)
因此,你可以编写这个函数如下:
int ipToInt(int first, int second,
int third, int fourth)
{
return (first << 24) | (second << 16) | (third << 8) | (fourth);
}
int
是有符号的,因此如果您将 192 向左移动 24 位,您将得到负整数,因此此代码对于高位字节的第一位为高位的情况是错误的。 - Mateusz可以尝试这些:
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();
}
Reverse()
返回 void
,因此您无法在其上调用 ToArray()
(对于未来的读者)。相反,将一个值分配给反转的字节,然后就可以调用 ToArray()
。 - Erik Philipsfe80::202:b3ff:fe1e:8329
的IPv6地址,它无法正常工作(无法完全还原)。 - ebhh2001在处理非常大的IP地址时,我遇到了一些问题,使用上述解决方案无法正常工作。 结果是byte[0]*16777216会溢出并成为负数int值。 对我有用的解决方法是进行简单的类型转换操作。
public static long ConvertIPToLong(string ipAddress)
{
System.Net.IPAddress ip;
if (System.Net.IPAddress.TryParse(ipAddress, out ip))
{
byte[] bytes = ip.GetAddressBytes();
return
16777216L * bytes[0] +
65536 * bytes[1] +
256 * bytes[2] +
bytes[3]
;
}
else
return 0;
}
由于没有人发布使用 BitConverter
并实际检查字节序的代码,因此在这里提供:
byte[] ip = address.Split('.').Select(s => Byte.Parse(s)).ToArray();
if (BitConverter.IsLittleEndian) {
Array.Reverse(ip);
}
int num = BitConverter.ToInt32(ip, 0);
并返回:
byte[] ip = BitConverter.GetBytes(num);
if (BitConverter.IsLittleEndian) {
Array.Reverse(ip);
}
string address = String.Join(".", ip.Select(n => n.ToString()));
uint
。而int
可以容纳相同的信息。如果你想将其存储在数据库中,那么int
更适合,但如果你想以无符号形式存储它,则需要使用bigint
。 - Guffauint
的形式,你也不能在地址栏中输入它,你必须先将其转换为文本形式才能这样做。仅仅因为使用最简单的将 int
转换为文本形式并不会产生可用的 IP 地址,并不是不使用它的好理由。 - Guffauint
,那是一个 uint
的文本表示。 - Guffa我将以上几个答案整合成了一个扩展方法,处理机器的字节序(即大小端)并处理映射到IPv6的IPv4地址。
public static class IPAddressExtensions
{
/// <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>
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");
}
}
单元测试:
[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);
}
}
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;
}
我的问题被关闭了,我不知道为什么。这里接受的答案与我需要的不同。
这给出了正确的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;
}
}
将UInt32转换为正确的小端格式后,这里有两个简单的转换函数:
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();
}
int
也无法容纳大于127.255.255.255
的地址,例如广播地址,因此请使用uint
。 - Saeb AminiNetworkToHostOrder
来反转字节。且int可以包含大于127.255.255.255
的地址;它们以负数形式存储。当将类型转换为int时,Address
属性中大于2^31的数字,即long
类型,会变成负数;将其转换为int是为了调用NetworkToHostOrder
,并且不会截断数字。 - Barry Kelly