Ipv6 D-如何验证IP地址是否有效

Ipv6 D-如何验证IP地址是否有效,ipv6,ipv4,d,phobos,Ipv6,Ipv4,D,Phobos,我正在编写一个HTTP解析库(因为我在纯D中找不到一个好的解析库),我需要能够验证IP地址(对于URI字段),所以我编写了两个函数来验证IP地址: 对于IPv4: bool isIPv4(string addr) { int parts; ulong idx; foreach (i, c; addr) { if (c == '.') { if (i == 0) { return false;

我正在编写一个HTTP解析库(因为我在纯D中找不到一个好的解析库),我需要能够验证IP地址(对于URI字段),所以我编写了两个函数来验证IP地址:

对于IPv4:

bool isIPv4(string addr) {
    int parts;
    ulong idx;

    foreach (i, c; addr) {
        if (c == '.') {
            if (i == 0) {
                return false;
            }

            if (to!int(addr[idx..i]) > 255) {
                return false;
            }

            parts++;
            if (parts > 3) {
                return false;
            }

            idx = i + 1;
        } else if (!isDigit(c)) {
            return false;
        }
    }

    if (to!int(addr[idx..addr.length]) > 255) {
        return false;
    }

    if (parts != 3) {
        return false;
    }

    return true;
}
对于IPv6:

bool isIPv6(string addr) {
    bool isColon, hasSeparator, hasIPv4;
    int leftChunks, rightChunks, digits;

    foreach (i, c; addr) {
        if (isHexDigit(c)) {
            digits = isColon ? 1 : digits + 1;
            isColon = false;

            if (digits == 1) {
                if (hasSeparator) {
                    rightChunks++;
                } else {
                    leftChunks++;
                }
            } else if (digits > 4) {
                return false;
            }
        } else if (c == ':') {
            if (isColon) {
                // multiple :: separators not allowed
                // as is :::
                if (hasSeparator) {
                    return false;
                }
                hasSeparator = true;
            } else {
                isColon = true;
            }
        } else if (c == '.') {
            if (hasSeparator) {
                rightChunks--;
            } else {
                leftChunks--;
            }

            if (!isIPv4(addr[i - digits .. addr.length])) {
                return false;
            }

            hasIPv4 = true;
            break;
        }
    }

    if (hasIPv4) {
        if (hasSeparator) {
            if (rightChunks + leftChunks > 5) {
                return false;
            }
        } else if (leftChunks != 6) {
            return false;
        }
    } else if (digits > 0) {
        if (hasSeparator) {
            if (rightChunks + leftChunks > 7) {
                return false;
            }
        } else if (leftChunks != 8) {
            return false;
        }
    }

    return true;
}
我最初试图为IPv6设计一个正则表达式,但这很痛苦,特别是因为有太多特殊情况(代码:),我想我遇到了一个正则表达式编译错误,因为它太长了。显然,我想使用一些标准函数来完成这项工作

FWIW,我使用std.arrays.split实现了IPv4验证程序,然后我决定这样做,因为否则我必须检测或捕获std.conv.to的异常!内部的

非常感谢

注意


最后,我想尝试将我编写的一些代码写入Phobos,因此我希望代码尽可能可靠。

您可以使用操作系统提供的inet\u pton()函数。它将解析一个地址,并告诉您地址是否错误。看


它将解析IPv4和IPv6地址,并且可以使用inet_ntop()将解析后的地址转换回其规范符号。

@tjameson:很久以前,我就入侵了自己的
uri
模块。以下是代码:。我一直想回到那个模块,改进它,并在GitHub提交一个拉请求,但从来没有时间去做。。。URI RFC还有一个正则表达式,用于解析URI中的IPv6地址,这肯定是我在这段代码中要用到的内容。

怎么样?

试试:

IPv4

IPv6

(使用ECMAscript语法)

发件人:

有没有跨平台的方式来称呼这一点?它会出现在std.linux和std.windows中吗?
inet\u pton
仅在以windows Vista开始的windows版本上可用。我知道它在标准C库中(准确地说是单UNIX规范v3,2001),因此它可能被移植到许多平台和语言。但我对D的了解还不够,无法为您指出正确的库。很抱歉遗憾的是,只有Win Vista支持它,但这是合乎逻辑的,因为较旧的Windows版本有一个完全不同的IP堆栈,IPv6只是在之后添加的。正则表达式的优点很好。我想我会重温正则表达式路线。我试图制作一个覆盖IPv6所有边缘情况的文件,但结果太长了(当我试图静态编译它时,D的正则表达式引擎吐了)。您知道IPv6有九种不同的形式吗?一旦您使用regexp从
dl.net.uri
获取主机,那么您只需调用
std.socket.parseUri(主机)
:)你知道它是否有任何DNS请求吗?对某些请求来说似乎是这样的,我想避免这种情况。由于我正在编写一个HTTP解析器,我只想知道它是什么类型的地址,IPv4、IPv6还是域名。好吧,你可以在这里亲眼看到:)文档上说:“不尝试名称解析。”它能得到多清晰?CyberShadow,如果文档的示例没有尝试使用address.toHostNameString()解析主机名,可能会更清楚。或者,如果解析失败时它没有抛出SocketException,而是抛出InvalidAddressException或类似的东西。谢谢!我一定错过了。我在那里看到了getAddressInfo注释,我没有看到任何地方没有尝试DNS解析。太谢谢你了!
/^(((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?!$)|$)){4}$
/^((?=(?=(.*?::))\2(?!.+::))(::)?([\dA-F]{1,4}:(:|(?!$))|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:(?!$)|$))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?!$)|$)){4})$/i