计算子网内的所有地址…用于IPv6

我已经看到很多很棒的C#示例 ,演示了如何将CIDR表示法(例如192.168.0.1/25)中提供的IPv4地址转换为相关范围(192.168.0.1 – 192.168.0.126)。 我的程序需要能够这样做(计算我本地子网中的所有地址),但我也想支持IPv6。

如果我的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的任务。

exNetworkLibrary是一个很棒的工具,但如果你不能在你的项目中使用它,那么你可能只想看到这篇文章:

http://www.codeproject.com/Articles/112020/IP-Address-Extension

它概述了如何计算地址掩码以用于IPv4。

您的问题与我看到的IPv6有关。自.Net 4.5以来,有一个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"); ///  /// 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 ///  ///  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); } 

我建议使用IPNetwork Library https://github.com/lduchosal/ipnetwork 。 从版本2开始,它也支持IPv4和IPv6。

IPv6的

  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 

玩得开心 !

我知道这篇文章已经过了5年了,但考虑到Google的function,它今天早上也可能已经更新了。 因此,我将从网络工程的角度添加一些说明。

这取决于什么样的地址。 如果您的意思是该范围内的每个地址,那么上述讨论是正确的。 如果您指的是可以唯一分配给子网中节点的地址(“单播”地址),请注意在IPv6(a)中没有广播,(b)存在大量的组播范围。

基本上:[subnet]:ff ::是为多播保留的。 如果您没有使用/ 64作为子网掩码,那么您真的要小心,因为它违背了一个基本假设,即许多与IPv6相关的RFC。 还有其他RFC出现警告不要使用全零主机地址(但我不知道对该效果的具体要求 )。

因此,对于/ 64子网,这意味着单播地址的范围是:: 0:0:0:1到:: feff:ffff:ffff:ffff。

请参阅此处以供讨论: http : //www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm

weylin