如果我的C#程序具有所有典型的ipconfig信息(IPv4地址、子网掩码、IPv6地址、链路本地v6地址、默认网关)- 我该如何生成本地子网中所有IPv6地址的列表并将其输出到控制台?
您可以使用eExNetworkLibrary中的eExNetworkLibrary.IP.IPAddressAnalysis类。
以下代码适用于IPv4和IPv6(已测试)。
string strIn = "2001:DB8::/120";
//Split the string in parts for address and prefix
string strAddress = strIn.Substring(0, strIn.IndexOf('/'));
string strPrefix = strIn.Substring(strIn.IndexOf('/') + 1);
int iPrefix = Int32.Parse(strPrefix);
IPAddress ipAddress = IPAddress.Parse(strAddress);
//Convert the prefix length to a valid SubnetMask
int iMaskLength = 32;
if(ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
iMaskLength = 128;
}
BitArray btArray = new BitArray(iMaskLength);
for (int iC1 = 0; iC1 < iMaskLength; iC1++)
{
//Index calculation is a bit strange, since you have to make your mind about byte order.
int iIndex = (int)((iMaskLength - iC1 - 1) / 8) * 8 + (iC1 % 8);
if (iC1 < (iMaskLength - iPrefix))
{
btArray.Set(iIndex, false);
}
else
{
btArray.Set(iIndex, true);
}
}
byte[] bMaskData = new byte[iMaskLength / 8];
btArray.CopyTo(bMaskData, 0);
//Create subnetmask
Subnetmask smMask = new Subnetmask(bMaskData);
//Get the IP range
IPAddress ipaStart = IPAddressAnalysis.GetClasslessNetworkAddress(ipAddress, smMask);
IPAddress ipaEnd = IPAddressAnalysis.GetClasslessBroadcastAddress(ipAddress, smMask);
//Omit the following lines if your network range is large
IPAddress[] ipaRange = IPAddressAnalysis.GetIPRange(ipaStart, ipaEnd);
//Debug output
foreach (IPAddress ipa in ipaRange)
{
Console.WriteLine(ipa.ToString());
}
Console.ReadLine();
我不完全确定是否已正确将前缀长度转换为包含子网掩码的字节数组,但这段代码应该可以为您提供很好的起点。
编辑:更新了代码的位操作部分。可能有些丑陋,但对于这个例子来说是有效的。如果需要的话,我认为您能够找到更好的解决方案。那些BitArrays真是让人头痛。
请注意,如果网络很大,则生成IPv6网络范围可能是一项非常耗费内存/ CPU资源的任务。
IPNetwork ipnetwork = IPNetwork.Parse("2001:0db8::/64");
Console.WriteLine("Network : {0}", ipnetwork.Network);
Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
Console.WriteLine("Usable : {0}", ipnetwork.Usable);
Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);
输出
Network : 2001:db8::
Netmask : ffff:ffff:ffff:ffff::
Broadcast :
FirstUsable : 2001:db8::
LastUsable : 2001:db8::ffff:ffff:ffff:ffff
Usable : 18446744073709551616
Cidr : 64
枚举
IPNetwork network = IPNetwork.Parse("::/124");
IPNetworkCollection ips = IPNetwork.Subnet(network, 128);
foreach (IPNetwork ip in ips) {
Console.WriteLine("{0}", ip);
}
输出
::/128
::1/128
::2/128
::3/128
::4/128
::5/128
::6/128
::7/128
::8/128
::9/128
::a/128
::b/128
::c/128
::d/128
::e/128
::f/128
玩得开心!
<子网>::
到<子网>:ffff:ffff:ffff:ffff
。子网没有保留地址(<子网>::
),而且IPv6没有广播的概念,因此在<子网>:ffff:ffff:ffff:ffff
不存在广播地址。 - Ron MaupinexNetworkLibrary是一款很棒的工具,但如果您的项目无法使用它,那么您可能只想看看这篇文章:
http://www.codeproject.com/Articles/112020/IP-Address-Extension
它概述了如何计算用于IPv4的地址掩码。IPAddress.MapToIPv6
方法。
https://msdn.microsoft.com/en-us/library/system.net.ipaddress.maptoipv6(v=vs.110).aspx
你可以使用文章中的检查来生成以下代码: private static IPAddress empty = IPAddress.Parse("0.0.0.0");
private static IPAddress intranetMask1 = IPAddress.Parse("10.255.255.255");
private static IPAddress intranetMask2 = IPAddress.Parse("172.16.0.0");
private static IPAddress intranetMask3 = IPAddress.Parse("172.31.255.255");
private static IPAddress intranetMask4 = IPAddress.Parse("192.168.255.255");
/// <summary>
/// Retuns true if the ip address is one of the following
/// IANA-reserved private IPv4 network ranges (from http://en.wikipedia.org/wiki/IP_address)
/// Start End
/// 10.0.0.0 10.255.255.255
/// 172.16.0.0 172.31.255.255
/// 192.168.0.0 192.168.255.255
/// </summary>
/// <returns></returns>
public static bool IsOnIntranet(this IPAddress ipAddress)
{
if (empty.Equals(ipAddress))
{
return false;
}
bool onIntranet = IPAddress.IsLoopback(ipAddress);
if (false == onIntranet)
{
//Handle IPv6 by getting the IPv4 Mapped Address.
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
onIntranet = ipAddress.Equals(ipAddress.And(intranetMask1.MapToIPv6())); //10.255.255.255
onIntranet = onIntranet || ipAddress.Equals(ipAddress.And(intranetMask4.MapToIPv6())); ////192.168.255.255
onIntranet = onIntranet || (intranetMask2.Equals(ipAddress.And(intranetMask2.MapToIPv6()))
&& ipAddress.Equals(ipAddress.And(intranetMask3.MapToIPv6())));
}
else
{
onIntranet = ipAddress.Equals(ipAddress.And(intranetMask1)); //10.255.255.255
onIntranet = onIntranet || ipAddress.Equals(ipAddress.And(intranetMask4)); ////192.168.255.255
onIntranet = onIntranet || (intranetMask2.Equals(ipAddress.And(intranetMask2))
&& ipAddress.Equals(ipAddress.And(intranetMask3)));
}
}
return onIntranet;
}
private static void CheckIPVersion(IPAddress ipAddress, IPAddress mask, out byte[] addressBytes, out byte[] maskBytes)
{
if (mask == null)
{
throw new ArgumentException();
}
addressBytes = ipAddress.GetAddressBytes();
maskBytes = mask.GetAddressBytes();
if (addressBytes.Length != maskBytes.Length)
{
throw new ArgumentException("The address and mask don't use the same IP standard");
}
}
public static IPAddress And(this IPAddress ipAddress, IPAddress mask)
{
byte[] addressBytes;
byte[] maskBytes;
CheckIPVersion(ipAddress, mask, out addressBytes, out maskBytes);
byte[] resultBytes = new byte[addressBytes.Length];
for (int i = 0, e = addressBytes.Length; i < e; ++i)
{
resultBytes[i] = (byte)(addressBytes[i] & maskBytes[i]);
}
return new IPAddress(resultBytes);
}
我知道这篇文章已经五年了,但考虑到谷歌的能力,它可能早上就被更新了。所以,我会从网络工程的角度添加一些澄清。
这取决于什么样的地址。如果你指的是范围内的每个地址,那么上面的讨论是正确的。如果你指的是可以唯一分配给子网中的节点的地址(“单播”地址),请注意,在IPv6中(a)没有广播,(b)有一个相当大的多播范围。
基本上:[子网]:ff:: 保留用于多播。如果你不使用/64作为子网掩码,你真的要小心,因为它违反了许多与IPv6相关的RFC的基本假设。还有其他的RFC警告不要使用全零主机地址(但我不知道是否有具体的要求)。
因此,对于/64子网,这意味着单播地址的范围是::0:0:0:1到::feff:ffff:ffff:ffff。
请参见此处的讨论: http://www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm
weylin
2001:DB8::/48
转换为2001:DB8:0:0:0:0:0:0 - 2001:DB8:0:FFFF:FFFF:FFFF:FFFF:FFFF
,而不是获取每个可能的地址。 - CodeNaked