如何从反向IP地址中获取长地址

huangapple go评论86阅读模式
英文:

How to get the long address from a reversed ip address

问题

这个问题与这篇文章有关。

我正在尝试编写一个用C#处理IPv4地址子网划分的工具。我知道有其他的库,最流行的是IpNetwork2。目前,该库无法加载到我的现有项目中,我需要继续前进。我最终将一个PowerShell模块SubnetTools转换成符合我的需求。问题是它依赖于已被弃用的IpAddress.Address属性。

为了简单起见,我将使用原始文章中的最短代码片段:

public int GetAddress(string ipAddress)
{
    string hex = string.Concat(ipAddress.Split('.').Reverse().Select(x => int.Parse(x).ToString("X").PadLeft(2, '0'))); // 0100007F 
    return Convert.ToInt32(hex, 16); //16777343
}

对于正常的IP地址,输出如预期,但反转后却给出了错误的值。请看下面的输出:

[IpTools.IpObject]::new('172.18.16.0')

ForwardIpAddress ForwardDecimalAddress ReverseIpAddress ReverseDecimalAddress
---------------- --------------------- ---------------- ---------------------
172.18.16.0                    1053356 0.16.18.172                -1408102400

以下是IpAddress的输出:

[ipaddress]'172.18.16.0';

AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv6UniqueLocal  : False
IsIPv4MappedToIPv6 : False
Address            : 1053356
IPAddressToString  : 172.18.16.0

[ipaddress]'0.16.18.172';

AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv6UniqueLocal  : False
IsIPv4MappedToIPv6 : False
Address            : 2886864896
IPAddressToString  : 0.16.18.172

反转后的Ip地址上的地址数字非常不同,我现有的代码方式意味着我获得了不正确的值。所以我的问题是,如何从IP地址0.16.18.172获取地址2886864896?或者如何在System.Net.IPAddress中完成这个操作?

我也非常乐意听取关于如何更好地处理子网划分的建议,而不使用NuGet包,到目前为止,我尝试过的两个都失败了。

与第一个评论相关,我的现有对象使用long类型的地址属性。

public string ForwardIpAddress { get; set; } = string.Empty;
public long ForwardDecimalAddress { get; set; } = 0;
public string ReverseIpAddress { get; set; } = string.Empty;
public long ReverseDecimalAddress { get; set; } = 0;

我使用了原始问题中的几个答案,但这里有一个示例返回一个long,但结果仍然相同。

public long GetAddress(string ipAddress)
{
    byte[] bytes = IPAddress.Parse(ipAddress).GetAddressBytes();
    if (!BitConverter.IsLittleEndian)
    {
        Array.Reverse(bytes);
    }
    long r = BitConverter.ToInt64(bytes, 0);
    return r;
}

根据评论,我已经更新了上面的代码片段以使用BitConverter.ToInt64()。当对反转运行时,会出现错误。

[IpTools.IpObject]::new('172.18.16.0')
MethodInvocationException: Exception calling ".ctor" with "1" argument(s): "Destination array is not long enough to copy all the items in the collection. Check array index and length. (Parameter 'value')"

GetAddress()对正向和反向都运行。

ForwardIpAddress = ip.ToString();
ForwardDecimalAddress = new Address().GetAddress(ForwardIpAddress);
ReverseIpAddress = reveresed.ToString();
ReverseDecimalAddress = new Address().GetAddress(ReverseIpAddress);
英文:

This question is related to this article

I'm trying to write a tool in C# to handle subnetting of IPv4 addresses. I know there are other libraries, the most popular being IpNetwork2. Currently that library doesn't load in my existing project, and I need to move forward. I wound up converting a PowerShell module, SubnetTools, to fit my needs. The problem is that it relies on the IpAddress.Address property which is deprecated.

For simplicity I'll use the shortest snip from the original article

        public int GetAddress(string ipAddress)
        {
            string hex = string.Concat(ipAddress.Split('.').Reverse().Select(x => int.Parse(x).ToString("X").PadLeft(2, '0'))); // 0100007F 
            return Convert.ToInt32(hex, 16); //16777343
        }

The output is as expected for the normal ip address but when reversed it gives the wrong value. See the output below:

[IpTools.IpObject]::new('172.18.16.0')

ForwardIpAddress ForwardDecimalAddress ReverseIpAddress ReverseDecimalAddress
---------------- --------------------- ---------------- ---------------------
172.18.16.0                    1053356 0.16.18.172                -1408102400

Here is the output from IpAddress:

[ipaddress]'172.18.16.0'

AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv6UniqueLocal  : False
IsIPv4MappedToIPv6 : False
Address            : 1053356
IPAddressToString  : 172.18.16.0

[ipaddress]'0.16.18.172'

AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv6UniqueLocal  : False
IsIPv4MappedToIPv6 : False
Address            : 2886864896
IPAddressToString  : 0.16.18.172

The address numbers on the reversed Ip are very different and the way that code I have works means I get the incorrect values. So I guess the question is, How do I get the address of 2886864896 from an ip address of 0.16.18.172. Or how is it done in System.Net.IPAddress?

I'm also very open to suggestions on better ways to deal with Subnetting without using nuget packages, thus far, the two I've tried have both failed.

Related to the first comment, my existing object uses long for the address properties.

public string ForwardIpAddress { get; set; } = string.Empty;
public long ForwardDecimalAddress { get; set; } = 0;
public string ReverseIpAddress { get; set; } = string.Empty;
public long ReverseDecimalAddress { get; set; } = 0;

I have used several answers from the original question but here is one sample that returns a long and I still get the same result.

        public long GetAddress(string ipAddress)
        {
            byte[] bytes = IPAddress.Parse(ipAddress).GetAddressBytes();
            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }
            long r = BitConverter.ToInt64(bytes, 0);
            return r;
        }

Per the comments I've updated the snip above to use BitConverter.ToInt64(). This results in an error when it runs on the reverse.

[IpTools.IpObject]::new('172.18.16.0')
MethodInvocationException: Exception calling ".ctor" with "1" argument(s): "Destination array is not long enough to copy all the items in the collection. Check array index and length. (Parameter 'value')"

The GetAddress() runs for both forward and reverse.

ForwardIpAddress = ip.ToString();
ForwardDecimalAddress = new Address().GetAddress(ForwardIpAddress);
ReverseIpAddress = reveresed.ToString();
ReverseDecimalAddress = new Address().GetAddress(ReverseIpAddress);

答案1

得分: 1

一个IPv4地址只有32位,因此您需要为传递给 BitConverter.ToInt64 的八位字节值提供一些填充:

public long GetAddress(string ipAddress)
{
    // 创建64位缓冲区
    byte[] bytes = new byte[8];

    // 将IP地址的字节复制到缓冲区
    IPAddress.Parse(ipAddress).GetAddressBytes().CopyTo(bytes, 0);
    if (!BitConverter.IsLittleEndian)
    {
        Array.Reverse(bytes);
    }
    
    return BitConverter.ToInt64(bytes, 0);
}
英文:

An IPv4 address is only 32 bits wide, so you need to provide some padding for the octect values passed to BitConverter.ToInt64:

public long GetAddress(string ipAddress)
{
    // create 64-bit buffer
    byte[] bytes = new byte[8];

    // copy ip address bytes to buffer
    IPAddress.Parse(ipAddress).GetAddressBytes().CopyTo(bytes, 0);
    if (!BitConverter.IsLittleEndian)
    {
        Array.Reverse(bytes);
    }
    
    return BitConverter.ToInt64(bytes, 0);
}

答案2

得分: 1

尝试以下:

string ip = "0.16.18.172";
string[] splitArray = ip.Split(new char[] { '.' });
byte[] bytes = splitArray.Select(x => byte.Parse(x)).ToArray();
uint number = BitConverter.ToUInt32(bytes);
英文:

Try following :

<!-- begin snippet: js hide: false console: true babel: false -->

            string ip = &quot;0.16.18.172&quot;;
            string[] splitArray = ip.Split(new char[] { &#39;.&#39; });
            byte[] bytes = splitArray.Select(x =&gt; byte.Parse(x)).ToArray();
            uint number = BitConverter.ToUInt32(bytes);

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月20日 21:57:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76730654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定