功能点 
  • 判断某个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.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


实现
  
   以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登录系统


[置顶] 如何判断两个IP大小关系及是否在同一个网段中的更多相关文章

  1. 判断两个IP是否处于同一子网(网段)

    如何去判断A和B两个IP是否在同一网段,假如有如下两个IP地址和子网掩码,判断他们是否是同一个网段的IP地址的方法: A IP:202.194.128.9 B IP:202.194.128.14 子网 ...

  2. 如何判断两个IP地址是不是在同一个网段

     要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果一网络号,如果网络号相同,就在同一子网,否则,不在同一子网. 例:假定选择了子网掩码255.255.254. ...

  3. 如何判断两个IP是否在同一网段

    下来举例说明,如何去判断A和B两个IP是否在同一网段. A IP:202.194.128.9 B IP:202.194.128.14 子网掩码:255.255.255.0 1.把A和B的地址转换为二进 ...

  4. 判断两个IP地址是不是属于同一子网的方法

    一个IP地址有三种写法: 第一种,单个IP,如192.168.55.28 第二种,IP/子网掩码,如192.168.55.28/255.255.255.0 第三种,IP/子网掩码长度,如192.168 ...

  5. 如何判断两个IP地址是不是处于同一网段?

    个人理解,欢迎指正. 一.要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果-->网络号,如果网络号相同, 就在同一子网,否则,不在同一子网. 例:假定选 ...

  6. python 判断两个ip地址是否属于同一子网

    python 判断两个ip地址是否属于同一子网 """ 判断两个IP是否属于同一子网, 需要判断网络地址是否相同 网络地址:IP地址的二进制与子网掩码的二进制地址逻辑&q ...

  7. 判断两个IP是否属于同一子网

    描述 子网掩码是用来判断任意两台计算机的IP地址是否属于同一子网络的根据.子网掩码与IP地址结构相同,是32位二进制数,其中网络号部分全为“1”和主机号部分全为“0”.利用子网掩码可以判断两台主机是否 ...

  8. python 判断两个ip是不是处于同一网段

    a_ip:10.10.15.100b_ip:10.10.15.101c_ip:10.10.10.100netmask:255.255.255.0 def numtobinary(num): binar ...

  9. POJ1269:Intersecting Lines(判断两条直线的关系)

    题目:POJ1269 题意:给你两条直线的坐标,判断两条直线是否共线.平行.相交,若相交,求出交点. 思路:直线相交判断.如果相交求交点. 首先先判断是否共线,之后判断是否平行,如果都不是就直接求交点 ...

随机推荐

  1. Structs 2

    1  redirect.redirectaction和chain 的区别 当使用type="redirectAction" 或type="redirect"提交 ...

  2. hdoj 2544 最短路(最短路+Dijkstrea算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 思路分析:该问题给定一个无向图,要求求从起始点到终点的最短路径长度:可以使用dijkstra算法 ...

  3. The document "ViewController.xib" could not be opened. Could not read archive.

    The document "ViewController.xib" could not be opened. Could not read archive. Please use ...

  4. openstack之Glance

    一.Glance简介.基本概念: Glance是openstack项目中负责镜像管理的模块,其功能包括虚拟机镜像的查找.注册和检索等操作. Glance提供restful API可以查询虚拟机镜像的m ...

  5. IOS中的自动布局

    Autolayout是一种“自动布局”技术,专门用来布局UI界面 Autolayout能很轻松地解决屏幕适配问题 Autolayout的两条核心概念:   >1 参照:通过参照其他控件或父控件来 ...

  6. Java多线程之非线程安全

    在Java多线程中我会重点总结五个如下的技术点: 1.非线程安全是如何出现的 2.synchronized对象监视器为Objec时的使用 3.synchronized对象监视器为Class时的使用 4 ...

  7. [译]Stairway to Integration Services Level 14 - 项目转换(SSIS 2008 ~ SSIS 2012)

    介绍 本文中我们会用SSDT把第一个SSIS项目转换为 SSIS 2012, 为什么要升级到2012? 你可能想使用SSIS 2012新的特性. 又或者想使用 SSIS 2012 Catalog. 想 ...

  8. C++对C语言的非面向对象特性扩充(3)

    今天要讲的是C++作用域运算符"::",强制类型转换的扩充,C++中相对于C中malloc和free函数的运算符new和delete,以及C++对C的一个重要扩充:引用(refer ...

  9. 打包jar类库与使用jar类库

    翻译人员: 铁锚 翻译时间: 2013年11月17日 原文链接:  Build a Java library by using jar file 代码复用是软件开发中很重要的一个原则.将常用的函数构建 ...

  10. CSS3框架!

    http://usablica.github.io/front-end-frameworks/compare.html?v=2.0