在Java中检查有效的IPv4地址

5

我正在使用sun.net.util.IPAddressUtil包来检查字符串是否包含有效的IPv4和IPv6地址。

代码片段如下:

String ipv4addr="200";

    if(IPAddressUtil.isIPv4LiteralAddress(ipv4addr))
    {
        System.out.println("valid ipv4 address");
    }
    else
    {
        System.out.println("not valid");

    }

但对于如200和300之类的地址,它仍然表示这是一个有效的IPv4地址,但实际上不是。 当我使用相同的软件包并检查IPv6地址时,它会显示:

String ipv6addr="200";

    if(IPAddressUtil.isIPv6LiteralAddress(ipv6addr))
    {
        System.out.println("valid ipv6 address");
    }
    else
    {
        System.out.println("not valid");

    }

我得到了正确的结果,但是IPv4似乎无法工作或者我使用它不正确。请指导我。我不想使用正则表达式来验证IPv4...

5
http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html - BalusC
是的,我看了这个链接...但我不认为他们为这个包提供了任何新版本或者提到的任何方法都已经过时了...我想最好使用Apache Common库进行这些验证......有什么建议吗? - AngelsandDemons
可能是验证IP地址的重复问题。 - Jason C
6个回答

23
你之所以得到“有效”的结果,是因为200是一个有效的IPv4地址。 对计算机而言,IPv4地址只是一个32位数字。点号完全是为了我们人类方便记忆大量精确数字。但它们不必存在;根据地址有多少部分,有关如何解析地址的规则。
当地址只包含一个数字时,它被视为32位数字,每个字节都是该数字的8位。如果将"200"解析为IP地址,则相当于0.0.0.200。同样,"2130706433"相当于127.0.0.1。
当地址有两个部分时,也有标准,例如0.200(第一部分是第一个字节,第二部分是表示其他3个字节的24位数字),甚至是0.0.200(前两个数字是字节,最后一部分是16位,占用另外2个字节)。这些“不寻常”的格式是IP地址类的剩余物,但几乎所有必须解析地址的软件都会理解它们。(例如,如果您打开浏览器并转到http://1249739112*或者甚至是http://74.125.33128*,Google的主页将出现。)

*请参阅可点击链接的评论。谢谢,“链接验证器”。:P

查看http://download.oracle.com/javase/6/docs/api/java/net/Inet4Address.htmlhttp://www.perlmonks.org/?node_id=221512,或http://en.wikipedia.org/wiki/IPv4#Address_representations获取更多细节。

Java同样理解这些格式(.net也一样,任何优秀的操作系统都是如此),并且无论地址包含1、2、3还是4部分,都可以正确解析该地址。

如果您想检查一个可能的地址是否实际上看起来像“xxx.xxx.xxx.xxx”,那么您可能需要使用模式显式检查它,或者使用验证库将32位数字视为无效地址(即使它们是有效的)。不过我觉得这没必要--如果您使用提供的查找函数,可以接受任何标准格式的地址,并且它将正常工作。

(所有这一切都随着IPv6而改变;有了更严格的格式,您不能只输入36位数字并期望它能正常工作。但是平台仍然知道如何解析地址,您应该相信它可以这样做。)


需要注意的是,IPv6地址的规则要严格得多。 - Joachim Sauer
@Joachim:已经注意到了。不过,说实话,我非常怀疑很多人在短时间内会尝试验证IPv6地址 :) - cHao
这意味着许多人将使用未经验证的IPv6地址。它们即将到来,如果您的软件不支持它们,那么您将被落在后面。 - Joachim Sauer
我听说“IPv6即将到来”已经十年了。还在等待中。我甚至无法在没有隧道代理的情况下使用IPV6。:P - cHao
谢谢cHao...我最好使用Apache Validator来检查IPV4地址...我不喜欢使用模式匹配和正则表达式... - AngelsandDemons
1
如果你打开浏览器并访问http://1249739112或者http://74.125.33128,例如,谷歌的主页会出现。 - cHao

3

请查看Guava的InetAddresses类,其中包含用于处理IP地址的静态实用程序方法。(据我了解,它在后台使用sun.net.util.IPAddressUtil类。)

System.out.println(InetAddresses.isInetAddress("400")); // false

是的,这对IPv4地址非常有效。但是我想从命令行接受一个IPv6地址。为了检查IPv6地址,我只能在这里看到isIsatapAddress(Inet6Address ip)方法。不确定如何从字符串获取Inet6address对象... - Thomas
@Thomas 我的答案中的代码仅用于测试IP地址。请查看此方法 - Kohányi Róbert

2

这是我在浏览 IPV4 验证时看到的第一个包。然而,最初我并不热衷于使用它。但似乎没有其他选择了... - AngelsandDemons

1
如果您想验证一个字符串是否是有效的IP地址表示形式,org.apache.http.conn.util.InetAddressUtils的源代码使用以下正则表达式:
IPV4_PATTERN = Pattern.compile(
    "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
IPV6_STD_PATTERN = Pattern.compile(
    "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
IPV6_HEX_COMPRESSED_PATTERN = Pattern.compile(
    "^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

1
那个字符串是IPv4字符串格式,最初由BSD Unix中的aton_inet实用程序引入,并在各种Unix和Linux版本以及其他地方一直存在至今。

https://linux.die.net/man/3/inet_aton

IPAddress Java库可以进行验证,并可配置为支持aton_inet格式或不支持。有关详细信息,请参阅链接处的javadoc。免责声明:我是该项目的经理。

验证地址是否有效,允许inet_aton样式:

    String str = "200";
    IPAddressString addrString = new IPAddressString(str);
    try {
         IPAddress addr = addrString.toAddress();
         System.out.println("valid address: " + addr.toCanonicalString());
    } catch(IPAddressStringException e) {
        System.out.println(e.getMessage());
    }

输出:

有效地址:0.0.0.200

验证地址是否有效,不允许使用inet_aton样式:

    IPAddressStringParameters parameters = new       
      IPAddressStringParameters.Builder().allow_inet_aton(false).toParams();
    addrString = new IPAddressString(str, parameters);
    try {
         IPAddress addr = addrString.toAddress();
         System.out.println("valid address: " + addr.toCanonicalString());
    } catch(IPAddressStringException e) {
        System.out.println(e.getMessage());
    }

输出:

200 IP地址错误:选项不允许IPv4地址少于四个段


0

经过一番小小的研究,我最终得出了这样的结果

    public static boolean isValidIP4Address(String ipAddress) {
        if (ipAddress.matches("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$")) {
            String[] groups = ipAddress.split("\\.");

            for (int i = 0; i <= 3; i++) {
                String segment = groups[i];
                if (segment == null || segment.length() <= 0) {
                    return false;
                }

                int value = 0;
                try {
                    value = Integer.parseInt(segment);
                } catch (NumberFormatException e) {
                    return false;
                }
                if (value > 255) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

这对于简单的检查来说是可以的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接