• [置顶] 如何判断两个IP大小关系及是否在同一个网段中


    功能点 
    • 判断某个IP地址是否合法
    • 判断两个IP地址是否在同一个网段中
    • 判断两个IP地址的大小关系
    知识准备

    基本原理

    IP地址范围
    0.0.0.0~ 255.255.255.255,包括了mask地址。

    IP地址划分
    • A类地址:1.0.0.1~126.255.255.254
    • B类地址:128.0.0.1~191.255.255.254
    • C类地址:192.168.0.0~192.168.255.255
    • D类地址:224.0.0.1239.255.255.254
    • E类地址:240.0.0.1255.255.255.254
    判断两个IP地址是否是同一个网段中
         要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果一网络号,如果网络号相同,就在同一子网,否则,不在同一子网。
         例:假定选择了子网掩码255.255.254.0,现在分别将上述两个IP地址分别与掩码做与运算,如下图所示:
    211.95.165.24 11010011 01011111 10100101 00011000
    255.255.254.0 11111111 11111111 111111110 00000000
    与的结果是: 11010011 01011111 10100100 00000000

    211.95.164.78 11010011 01011111 10100100 01001110
    255.255.254.0 11111111 11111111 111111110 00000000
    与的结果是: 11010011 01011111 10100100 00000000
         可以看出,得到的结果(这个结果就是网络地址)都是一样的,因此可以判断这两个IP地址在同一个子网。

         如果没有进行子网划分,A类网络的子网掩码为255.0.0.0,B类网络的子网掩码为255.255.0.0,C类网络的子网掩码为255.255.255.0,缺省情况子网掩码为255.255.255.0

    实现
          以Java语言实现,主要针对IPv4地址。
          代码实现如下(包括注释):
    package org.slive.net;
    
    import java.net.UnknownHostException;
    import java.util.regex.Pattern;
    
    /**
    * <pre>
    * IP地址范围:
    * 0.0.0.0~255.255.255.255,包括了mask地址。
    *
    * IP地址划分:
    * A类地址:1.0.0.1~126.255.255.254
    * B类地址:128.0.0.1~191.255.255.254
    * C类地址:192.168.0.0~192.168.255.255
    * D类地址:224.0.0.1~239.255.255.254
    * E类地址:240.0.0.1~255.255.255.254
    *
    * 如何判断两个IP地址是否是同一个网段中:
    * 要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果一网络号,如果网络号相同,就在同一子网,否则,不在同一子网。
    * 例:假定选择了子网掩码255.255.254.0,现在分别将上述两个IP地址分别与掩码做与运算,如下图所示:
    * 211.95.165.24 11010011 01011111 10100101 00011000
    * 255.255.254.0 11111111 11111111 111111110 00000000
    * 与的结果是: 11010011 01011111 10100100 00000000
    *
    * 211.95.164.78 11010011 01011111 10100100 01001110
    * 255.255.254.0 11111111 11111111 111111110 00000000
    * 与的结果是: 11010011 01011111 10100100 00000000
    * 可以看出,得到的结果(这个结果就是网络地址)都是一样的,因此可以判断这两个IP地址在同一个子网。
    *
    * 如果没有进行子网划分,A类网络的子网掩码为255.0.0.0,B类网络的子网掩码为255.255.0.0,C类网络的子网掩码为255.255.255.0,缺省情况子网掩码为255.255.255.0
    *
    * @author Slive
    */
    public class IpV4Util
    {
         // IpV4的正则表达式,用于判断IpV4地址是否合法
         private static final String IPV4_REGEX = "((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3})";
        
         // 系统子网掩码,它与ip组成一个地址
         private int mask;
        
         // 1代表A类,2代表B类,3代表C类;4代表其它类型
         public final static int IP_A_TYPE = 1;
         public final static int IP_B_TYPE = 2;
         public final static int IP_C_TYPE = 3;
         public final static int IP_OTHER_TYPE = 4;
        
         // A类地址范围:1.0.0.1---126.255.255.254
         private static int[] IpATypeRange;
         // B类地址范围:128.0.0.1---191.255.255.254
         private static int[] IpBTypeRange;
         // C类地址范围:192.168.0.0~192.168.255.255
         private static int[] IpCTypeRange;
        
         // A,B,C类地址的默认mask
         private static int DefaultIpAMask;
         private static int DefaultIpBMask;
         private static int DefaultIpCMask;
        
         // 初始化
         static
         {
              IpATypeRange = new int[2];
              IpATypeRange[0] = getIpV4Value("1.0.0.1");
              IpATypeRange[1] = getIpV4Value("126.255.255.254");
             
              IpBTypeRange = new int[2];
              IpBTypeRange[0] = getIpV4Value("128.0.0.1");
              IpBTypeRange[1] = getIpV4Value("191.255.255.254");
             
              IpCTypeRange = new int[2];
              IpCTypeRange[0] = getIpV4Value("192.168.0.0");
              IpCTypeRange[1] = getIpV4Value("192.168.255.255");
             
              DefaultIpAMask = getIpV4Value("255.0.0.0");
              DefaultIpBMask = getIpV4Value("255.255.0.0");
              DefaultIpCMask = getIpV4Value("255.255.255.0");
         }
        
         /**
         * 默认255.255.255.0
         */
         public IpV4Util()
         {
              mask = getIpV4Value("255.255.255.0");
         }
        
         /**
         * @param mask 任意的如"255.255.254.0"等格式,如果格式不合法,抛出UnknownError异常错误
         */
         public IpV4Util(String masks)
         {
              mask = getIpV4Value(masks);
              if(mask == 0)
              {
                   throw new UnknownError();
              }
         }
        
         public int getMask()
         {
              return mask;
         }
        
         /**
         * 比较两个ip地址是否在同一个网段中,如果两个都是合法地址,两个都是非法地址时,可以正常比较;
         * 如果有其一不是合法地址则返回false;
         * 注意此处的ip地址指的是如“192.168.1.1”地址,并不包括mask
         * @return
         */
         public boolean checkSameSegment(String ip1,String ip2)
         {
              return checkSameSegment(ip1,ip2,mask);
         }
        
         /**
         * 比较两个ip地址是否在同一个网段中,如果两个都是合法地址,两个都是非法地址时,可以正常比较;
         * 如果有其一不是合法地址则返回false;
         * 注意此处的ip地址指的是如“192.168.1.1”地址
         * @return
         */
         public static boolean checkSameSegment(String ip1,String ip2, int mask)
         {
              // 判断IPV4是否合法
              if(!ipV4Validate(ip1))
              {
                   return false;
              }
              if(!ipV4Validate(ip2))
              {
                   return false;
              }
              int ipValue1 = getIpV4Value(ip1);
              int ipValue2 = getIpV4Value(ip2);
              return (mask & ipValue1) == (mask & ipValue2);
         }
        
         /**
         * 比较两个ip地址是否在同一个网段中,如果两个都是合法地址,两个都是非法地址时,可以正常比较;
         * 如果有其一不是合法地址则返回false;
         * 注意此处的ip地址指的是如“192.168.1.1”地址
         * @return
         */
         public static boolean checkSameSegmentByDefault(String ip1,String ip2)
         {
              int mask = getDefaultMaskValue(ip1);     // 获取默认的Mask
              return checkSameSegment(ip1,ip2,mask);
         }
        
         /**
         * 获取ip值与mask值与的结果
         * @param ipV4
         * @return  32bit值
         */
         public int getSegmentValue(String ipV4)
         {
              int ipValue = getIpV4Value(ipV4);
              return (mask & ipValue);
         }
        
         /**
         * 获取ip值与mask值与的结果
         * @param ipV4
         * @return  32bit值
         */
         public static int getSegmentValue(String ip, int mask)
         {
              int ipValue = getIpV4Value(ip);
              return (mask & ipValue);
         }
        
         /**
         * 判断ipV4或者mask地址是否合法,通过正则表达式方式进行判断
         * @param ipv4
         */
        public static boolean ipV4Validate(String ipv4)
        {
             return ipv4Validate(ipv4,IPV4_REGEX);
        }
       
        private static boolean ipv4Validate(String addr,String regex)
        {
              if(addr == null)
              {
                  return false;
             }
             else
             {
                  return Pattern.matches(regex, addr.trim());
             }
         }
       
         /**
         * 比较两个ip地址,如果两个都是合法地址,则1代表ip1大于ip2,-1代表ip1小于ip2,0代表相等;
         * 如果有其一不是合法地址,如ip2不是合法地址,则ip1大于ip2,返回1,反之返回-1;两个都是非法地址时,则返回0;
         * 注意此处的ip地址指的是如“192.168.1.1”地址,并不包括mask
         * @return
         */
         public static int compareIpV4s(String ip1,String ip2)
         {
              int result = 0;
              int ipValue1 = getIpV4Value(ip1);     // 获取ip1的32bit值
              int ipValue2 = getIpV4Value(ip2); // 获取ip2的32bit值
              if(ipValue1 > ipValue2)
              {
                   result =  -1;
              }
              else if(ipValue1 <= ipValue2)
              {
                   result = 1;
              }
              return result;
         }
        
         /**
         * 检测ipV4 的类型,包括A类,B类,C类,其它(C,D和广播)类等
         * @param ipV4
         * @return     返回1代表A类,返回2代表B类,返回3代表C类;返回4代表D类
         */
         public static int checkIpV4Type(String ipV4)
         {
              int inValue = getIpV4Value(ipV4);
              if(inValue >= IpCTypeRange[0] && inValue <= IpCTypeRange[1])
              {
                   return IP_C_TYPE;
              }
              else if(inValue >= IpBTypeRange[0] && inValue <= IpBTypeRange[1])
              {
                   return IP_B_TYPE;
              }
              else if(inValue >= IpATypeRange[0] && inValue <= IpATypeRange[1])
              {
                   return IP_A_TYPE;
              }
              return IP_OTHER_TYPE;
         }
        
         /**
         * 获取默认mask值,如果IpV4是A类地址,则返回{@linkplain #DefaultIpAMask},
         * 如果IpV4是B类地址,则返回{@linkplain #DefaultIpBMask},以此类推
         * @param anyIpV4 任何合法的IpV4
         * @return mask 32bit值
         */
         public static int getDefaultMaskValue(String anyIpV4)
         {
              int checkIpType = checkIpV4Type(anyIpV4);
              int maskValue = 0;
              switch (checkIpType)
              {
                   case IP_C_TYPE:
                        maskValue = DefaultIpCMask;
                        break;
                   case IP_B_TYPE:
                        maskValue = DefaultIpBMask;
                        break;
                   case IP_A_TYPE:
                        maskValue = DefaultIpAMask;
                        break;
                   default:
                        maskValue = DefaultIpCMask;
              }
              return maskValue;
         }
        
         /**
         * 获取默认mask地址,A类地址对应255.0.0.0,B类地址对应255.255.0.0,
         * C类及其它对应255.255.255.0
         * @param anyIp
         * @return mask 字符串表示
         */
         public static String getDefaultMaskStr(String anyIp)
         {
              return trans2IpStr(getDefaultMaskValue(anyIp));
         }
        
         /**
         * 将ip 32bit值转换为如“192.168.0.1”等格式的字符串
         * @param ipValue 32bit值
         * @return
         */
         public static String trans2IpStr(int ipValue)
         {
              // 保证每一位地址都是正整数
              return ((ipValue >> 24) & 0xff) + "." + ((ipValue >> 16) & 0xff) + "." + ((ipValue >> 8) & 0xff) + "." + (ipValue & 0xff);
         }
        
         /**
         * 将ip byte数组值转换为如“192.168.0.1”等格式的字符串
         * @param ipBytes 32bit值
         * @return
         */
        public static String trans2IpV4Str(byte[] ipBytes)
        {
             // 保证每一位地址都是正整数
             return (ipBytes[0] & 0xff) + "." + (ipBytes[1] & 0xff) + "." + (ipBytes[2] & 0xff) + "." + (ipBytes[3] & 0xff);
        }
    
         public static int getIpV4Value(String ipOrMask)
         {
              byte[] addr = getIpV4Bytes(ipOrMask);
              int address1  = addr[3] & 0xFF;
              address1 |= ((addr[2] << 8) & 0xFF00);
              address1 |= ((addr[1] << 16) & 0xFF0000);
              address1 |= ((addr[0] << 24) & 0xFF000000);
              return address1;
         }
    
         public static byte[] getIpV4Bytes(String ipOrMask)
         {
              try
              {
                   String[] addrs = ipOrMask.split("\.");
                   int length = addrs.length;
                   byte[] addr = new byte[length];
                   for (int index = 0; index < length; index++)
                   {
                        addr[index] = (byte) (Integer.parseInt(addrs[index]) & 0xff);
                   }
                   return addr;
              }
              catch (Exception e)
              {
              }
              return new byte[4];
         }
    }
    

    应用
      public static void main(String[] args) throws UnknownHostException
          {
                 // 判断ip两个地址的大小关系
                String ip1 = "10.8.9.116";
                String ip2 = "10.8.9.10";
                System. out.println("ip1 大于 ip2? " + (compareIpV4s (ip1, ip2) > 0));
    
                String ip3= "10.8.8.116";
                String ip4 = "10.10.9.10";
                
                System. out.println("ip3 大于 ip4? " + (compareIpV4s (ip3, ip4) > 0));
                
                 // 判断ip两个地址是否是同一个网段
                 int mask1 = getIpV4Value( "255.255.255.0");
                 int mask2 = getIpV4Value( "255.255.0.0");
                
                System. out.println("ip1和ip2在同一个网段中? " + (checkSameSegment(ip1, ip2, mask1)));
                
                System. out.println("ip3和ip4在同一个网段中 ?" + (checkSameSegment(ip3, ip4, mask2)));
                
                 // 判断ip5是否在ip1和ip2范围中
                String ip5= "10.8.8.8";
                       // 假设ip1和ip2在同一个网段中,并且ip1为起始地址,ip2为结束地址,ip1<=1
                       // 比较ip1与ip5是否在同一个网段中
                       if(checkSameSegment(ip1, ip5, mask1))
                      {
                             // 判断ip5是否在ip1和ip2范围中
                             if(((compareIpV4s(ip5, ip1)) >= 0) && (compareIpV4s(ip5, ip2) <= 0))
                            {
                                  System. out.println("ip5 在ip1-ip2范围内" );
                            }
                             else if ((compareIpV4s(ip5, ip1)) < 0)
                            {
                                  System. out.println("ip5 不在ip1-ip2范围内,因为ip5小于ip1" );
                            }
                             else
                            {
                                  System. out.println("ip5 不在ip1-ip2范围内,因为ip5大于ip2" );
                            }
                      }
                       else
                      {
                            System. out.println("ip5 不在ip1-ip2范围内,因为ip5不在ip1的网段中" );
                      }
          }
    

    总结
    • 了解正在表达式,并懂得编写判断IP地址是否合法的表达式
    • 了解判断IpV4地址是否在同一个网段的原理,并能够用Java语言实现

    优化与扩展
    • 另一种判断IpV4地址合法性的方法(不通过正在表达式)
    • 判断IpV4是否是A类地址,或者B类地址,又或者是广播地址等
    • 多个IpV4地址是否在同一个网段中
    • 客户端,服务器端安全策略实现——限制特点的用户IP登录系统


  • 相关阅读:
    引爆点--产品方法论
    智能的差旅预订 竞品分析
    差旅管理
    运营中的用户心理学
    鸡汤
    励志的鸡汤
    cmder安装
    jQuery height() innerHeight() outerHight() width() innerWidth() outerWidth()源码解读
    css未知宽度水平居中整理
    css水平垂直居中块整理
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3297171.html
Copyright © 2020-2023  润新知