验证InetSocketAddresses(ipv4/v6 +端口地址)的正则表达式

4
我正在寻找针对ipv4和ipv6 InetSocketAddress(即IP地址+端口号)的测试过的正则表达式。我不关心验证主机名。
可以使用两个正则表达式(一个用于ipv4,一个用于ipv6),也可以使用一个组合正则表达式。
有人有任何分享吗? 编辑 有关ip4格式信息,请参见here,有关ipv6格式信息,请参见here。然后,使用“:”添加端口号。 编辑2 要创建字符串表示形式,我将按如下方式进行:
byte[] tmp = { 10, 1, 0, 0 };
InetSocketAddress isa = new InetSocketAddress(
        InetAddress.getByAddress(tmp), 443);

返回:

/10.1.0.0:443

任何由InetSocketAddress.toString()生成的内容。我想通过解析这些字符串来检查和重新创建ISA。注意:ISA始终具有端口。 - Jérôme Verstrynge
@JVerstry,我认为你的更新不正确。我刚刚尝试了一个测试用例,在其中构造了一个new InetSocketAddress(InetAddress.getByName("10.1"), 443);.toString()/10.0.0.1:443。如果您在.toString()上运行正则表达式,例如,我认为您不必担心非规范化的IPv4地址,例如x.x格式。这是在Windows上使用Java版本1.6.0_21-b07 - mpontillo
以下是第三个例子:new InetSocketAddress(InetAddress.getByName("fe80::1%22"), 443)的.toString()返回/fe80:0:0:0:0:0:0:1%22:443。 - mpontillo
@Mike 我已经再次更新了问题,但也许这种情况是无法解决的,因为我们对Java在这种情况下的行为了解不足(即过于不可预测)。 - Jérôme Verstrynge
我需要将Ipv4/6 +端口号地址存储为字符串格式。我已经实现了一种解决方案,其中我检索byte[]并使用base 64进行转换。然后我附加'_'和端口号。反向操作很容易。我希望有一个正则表达式的解决方案是可能的... - Jérôme Verstrynge
显示剩余6条评论
3个回答

3
尝试在InetSocketAddress.toString() 上使用正则表达式可能不是一个好主意(请参见上面问题的评论)。一种可能的替代方法是使用URLURI将地址以字符串格式输出,这样做更加标准化
另一方面,如果你想用正则表达式折磨自己... ;-)
IPv4:
      Pattern: .*/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+):([0-9]+)
Java constant: ".*/([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+):([0-9]+)"

仅处理点分十进制格式的地址。不会检测无效的地址。

IPv6:

      Pattern: .*/([0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+(%[a-zA-Z0-9]+)?):([0-9]+)
Java constant: ".*/([0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+(%[a-zA-Z0-9]+)?):([0-9]+)"

处理包含所有8个16位节的IPv6地址。(请注意,这仅能正常工作是因为Java中的Inet6Address实现似乎以非标准方式打印地址 - 可能是为了附加端口号并且没有歧义)。不检测无效的IPv6地址。仅处理小写十六进制字符。使用大写或小写字母和/或数字处理区域/范围ID(如果存在)。
我用找到的方便小程序测试了它们。
顺便说一句,我仍然认为这是个坏主意。;-) 我不能确定所有Java平台都会以这种方式打印地址。

谢谢。为了记录,我使用了URI,因为URL不接受“tcp”架构/协议。 - Jérôme Verstrynge

2

1
你看过链接了吗?它列出了一些正则表达式,包括网络地址。 - Santa
例如,IPv6:^([0-9a-fA-F]{4}|0)(\:([0-9a-fA-F]{4}|0)){7}$。IPv4 IPv6:([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(\d{1,3}\.){3}\d{1,3}。还有其他变化。 - Santa
1
@Santa 是的,我确实看了链接,但是它们在哪里考虑端口号(即,您是否完全阅读了问题)?此外,存在不匹配的值,应该是相反的。这些正则表达式有缺陷.. 它们没有回答我的问题! - Jérôme Verstrynge

1

不好的想法。使用RFC 5952格式的IPv6地址不是一种常规语言,因此使用正则表达式解析它们会导致失败。请使用适当的解析函数,例如POSIX inet_pton函数。Java应该在某个地方有一个。谁知道,它甚至可能足够聪明,能够根据RFC 5952第5节处理带有嵌入式IPv4子字段的IPv6地址。

说真的...不要使用正则表达式来做这件事。


inet_pton()InetAddress.getByName() 的等价物。Java 会为您解决所有问题。我发布的正则表达式之所以有效,仅因为 InetAddress 以一种奇怪的方式(我想是不正确的)以常规方式打印地址。例如,new InetSocketAddress(InetAddress.getByName("fe80::192.168.0.1%22"), 443) 返回 /fe80:0:0:0:0:0:c0a8:1%22:443 - mpontillo

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