C#查询本机所在网段的所有IP以及计算目标IP对应同局域网的本机IP

发布时间 2023-07-15 16:32:38作者: TanZhiWei

1 借助System.Net.NetworkInformation.NetworkInterface 作为切入点获取所有的网卡接口

2 通过NetworkInterface.OperationalStatus 状态判断是否可以传送包

3 通过NetworkInterface.NetworkInterfaceType 判断网卡类型

4 通过UnicastIPAddressInformation.Address 和 UnicastIPAddressInformation.IPv4Mask 计算局域网的所有IP

具体代码如下:

using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace Utils
{
    /// <summary>
    /// 子网IP范围查询
    /// </summary>
    public static class SubNetIps
    {
        /// <summary>
        /// 获取所有IP网段
        /// </summary>
        /// <returns></returns>
        public static List<IpRange> GetIpRanges()
        {
            var ranges = new List<IpRange>();
            foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
            {
                var ipProps = GetIpInterfaceProperties(netInterface);
                if (ipProps == null) continue;
                foreach (var addressInfo in ipProps.UnicastAddresses)
                {
                    //忽略非IP4的地址
                    if (addressInfo.Address.AddressFamily != AddressFamily.InterNetwork) continue;
                    var lowestAddress = GetLowestIp(addressInfo.Address, addressInfo.IPv4Mask);
                    var highestAddress = GetHighestIp(addressInfo.Address, addressInfo.IPv4Mask);
                    ranges.Add(new IpRange(lowestAddress, highestAddress));
                }
            }
            return ranges;
        }

        /// <summary>
        /// 获取匹配远方的本地
        /// </summary>
        /// <returns></returns>
        public static IPAddress GetLocalIpByRemoteAddress(IPAddress remoteAddress)
        {
            foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
            {
                var ipProps = GetIpInterfaceProperties(netInterface);
                if (ipProps == null) continue;
                foreach (var addressInfo in ipProps.UnicastAddresses)
                {
                    //忽略非IP4的地址
                    if (addressInfo.Address.AddressFamily != AddressFamily.InterNetwork) continue;
                    var lowestAddress = GetLowestIp(addressInfo.Address, addressInfo.IPv4Mask);
                    var highestAddress = GetHighestIp(addressInfo.Address, addressInfo.IPv4Mask);
                    if (IsBetween(remoteAddress, lowestAddress, highestAddress)) return addressInfo.Address;
                }
            }
            return default(IPAddress);
        }

        /// <summary>
        /// 获取局域网以及能够上网的网卡信息
        /// </summary>
        /// <param name="netInterface"></param>
        /// <returns></returns>
        private static IPInterfaceProperties GetIpInterfaceProperties(NetworkInterface netInterface)
        {
            IPInterfaceProperties ipProps = null;
            if (netInterface.OperationalStatus != OperationalStatus.Up) return null;

            ipProps = netInterface.GetIPProperties();
            if (netInterface.NetworkInterfaceType != NetworkInterfaceType.Wireless80211)
            {
                //忽略默认网关地址为空的适配器
                var dhcpServerAddresses = ipProps.DhcpServerAddresses;
                if (dhcpServerAddresses.Count == 0)
                    ipProps = null;
            }
            return ipProps;
        }

        private static bool IsBetween(IPAddress ipAddress, IPAddress startIP, IPAddress endIP)
        {
            var startBytes = startIP.GetAddressBytes();
            var endBytes = endIP.GetAddressBytes();
            var targetBytes = ipAddress.GetAddressBytes();
            if (startBytes.Length != targetBytes.Length || endBytes.Length != targetBytes.Length) return false;
            bool isBetween = true;
            for (int i = 0; i < startBytes.Length; i++)
            {
                if (startBytes[i] > targetBytes[i] || endBytes[i] < targetBytes[i])
                {
                    isBetween = false;
                    break;
                }
            }
            return isBetween;
        }

        private static IPAddress GetLowestIp(IPAddress address, IPAddress mask)
        {
            byte[] addressBytes = address.GetAddressBytes();
            byte[] maskBytes = mask.GetAddressBytes();
            if (addressBytes.Length != 4 || maskBytes.Length != 4)
                return IPAddress.None;
            byte[] lowest = new byte[4];
            for (var i = 0; i < 4; i++)
                lowest[i] = (byte)(addressBytes[i] & maskBytes[i]);
            return new IPAddress(lowest);
        }
        private static IPAddress GetHighestIp(IPAddress address, IPAddress mask)
        {
            byte[] addressBytes = address.GetAddressBytes();
            byte[] maskBytes = mask.GetAddressBytes();
            if (addressBytes.Length != 4 || maskBytes.Length != 4)
                return IPAddress.None;
            byte[] highest = new byte[4];
            for (var i = 0; i < 4; i++)
                highest[i] = (byte)((addressBytes[i] & maskBytes[i]) | ~maskBytes[i]);
            return new IPAddress(highest);
        }
    }

    public class IpRange
    {
        /// <summary>
        /// 最小动态IP
        /// </summary>
        public IPAddress LowestAddress { get; }
        /// <summary>
        /// 最大可分配动态IP
        /// </summary>
        public IPAddress HighestAddress { get; }

        public IpRange(IPAddress lowestAddress, IPAddress highestAddress)
        {
            LowestAddress = lowestAddress;
            HighestAddress = highestAddress;
        }
    }
}