经典 ASP 中 ipv6 地址的字符串表示 有用的链接

问题描述

出于地理定位的目的,我试图获取 ip v6 地址的数值的字符串表示。 由于经典 ASP 不处理 bigint 值,我正在尝试使用 Javascript 函数解决它。

基于这个使用 https://jsfiddle.net/adamish/mrx3880p/ 库的工作 fiddle: biginteger.js,我修改了该库以用作 ASP 的有效包含。

var ip = '2a00:85c0:0001:0000:0000:0000:0241:0023';


// simulate your address.binaryZeroPad(); method
var parts = [];
ip.split(":").forEach(function(it) {
    var bin = parseInt(it,16).toString(2);
    while (bin.length < 16) {
        bin = "0" + bin;
    }
    parts.push(bin);
})
var bin = parts.join("");

// Use BigInteger library
var dec = bigInt(bin,2).toString();
console.log(dec);

fiddle 中的代码将 ipv6 转换为其二进制表示,然后调用 toString 函数,请求以 2 为基数进行转换。

它适用于小提琴。但是,我无法让它在我的代码中工作,因为返回值采用科学计数法,这对我不利。

目标是输入字符串“2a00:85c0:1::241:23”(或其非缩短版本,“2a00:85c0:0001:0000:0000:0000:0241:0023”,不物质)并输出数字等效的字符串表示形式,或“55830288595252163998698714105846497315”。

由于我只能在经典 ASP 中使用什么,有没有人知道如何使转换工作?

解决方法

很遗憾,您将无法执行此操作,因为 VBScript 和 JScript 无法处理所需的数值精度。

这是我第一次尝试 VBScript

<%
Option Explicit
Const base = 65536
Dim ipv6: ipv6 = "2a00:85c0:0001:0000:0000:0000:0241:0023"
Dim pwr: pwr = 8
Dim hextets: hextets = Split(ipv6,":")
Dim hextet,ipnum
If IsArray(hextets) Then
  For Each hextet In hextets
    pwr = pwr - 1
    ipnum = ipnum + ((base^pwr) * CLng("&h" & hextet))
  Next
End If
%>
<!doctype html>
<html>
  <head>
    <title>IPv6 to IP Number</title>
  </head>

  <body>
    <pre><%= ipv6 %></pre>
    <pre><%= FormatNumber(ipnum,-2,false) %></pre>
  </body>
</html>

输出:

2a00:85c0:0001:0000:0000:0000:0241:0023
55830288595252200000000000000000000000

这里的问题是计算是正确的,但数字不能处理精度,所以当它达到最大值时,它默认为 0

我的下一次尝试是 JScript(不是我最强的语言)

<% @Language = "JScript" %>
<%
var base = 65536;
var ipv6 = "2a00:85c0:0001:0000:0000:0000:0241:0023";
var pwr = 8;
var hextets = ipv6.split(":");
var ipnum;

for (var hextet in hextets) {
  pwr--;
  ipnum += (Math.pow(base,pwr) * parseInt("0x" + hextets[hextet]));
};
%>
<!doctype html>
<html>
  <head>
    <title>IPv6 to IP Number</title>
  </head>

  <body>
    <pre><%= ipv6 %></pre>
    <pre><%= ipnum %></pre>
  </body>
</html>

输出:

2a00:85c0:0001:0000:0000:0000:0241:0023
-1.#IND

这次它失败了,出现了 -1.#IND conversion error,这基本上意味着数字太大而无法表示。

因此,虽然不能直接在 VBScript 或 JScript 中执行,但您仍然可以使用另一种语言(C#、VB.Net 等)构建一个公开 COM 的类,该类进行计算并生成 VBScript/Jscript 可以显示的字符串。


有用的链接

,

我删除了我之前的答案,因为它不是很有帮助。已经确定您不能使用 Classic ASP 将 IPv6 地址转换为使用 VBscript 的数值。 JScript 可能是可能的,但似乎不太可能。

我还在一个高流量的经典 ASP 网站上转换和记录 IPv4/6 数值以用于地理定位。

对于 IPv4,使用 VBscript 进行转换非常简单:

Function IPv4ToNumber(ByVal IPv4)

    Dim i,Pos,PrevPos,Num

    For i = 1 To 4

        Pos = InStr(PrevPos + 1,IPv4,".",1)
        If i = 4 Then pos = Len(IPv4) + 1
        Num = Int(Mid(IPv4,PrevPos + 1,Pos - PrevPos - 1))
        PrevPos = Pos
        IPv4ToNumber = ((Num Mod 256) * (256 ^ (4 - i))) + IPv4ToNumber

    Next

End function

这是另一个有用的 VBscript 函数,它返回 IP 的类型(IPv4、IPv6 或无效 IP 的空字符串)。你可以只使用 InStr():

. = IPv4

: = IPv6

但是这个函数使用正则表达式来正确验证 IP 地址:

Function IP_Type(ByVal IP)

    IP_Type = "" ' Default
    
    ' Check for valid IPv4 and IPv6 addresses
    
    Dim IP_RegExp
    
    If Len(IP) >= 7 AND Len(IP) <= 15 Then
    
        ' Potential IPv4
        
        Set IP_RegExp = New RegExp
        
            IP_RegExp.Pattern = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
            IP_Type = IP_RegExp.Test(IP)
            
            If IP_Type Then IP_Type = "IPv4" Else IP_Type  = ""
        
        Set IP_RegExp = Nothing
    
    ElseIf Len(IP) > 15 AND Len(IP) <= 39 Then
    
        ' Potential IPv6
        
        Set IP_RegExp = New RegExp
        
            IP_RegExp.Pattern = "^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,6}:[0-9a-fA-F]{1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,3}|([0-9a-fA-F]{1,3}(:[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,6})|:((:[0-9a-fA-F]{1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9])|([0-9a-fA-F]{1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]))$"
            IP_Type = IP_RegExp.Test(IP)
            
            If IP_Type Then IP_Type = "IPv6" Else IP_Type  = ""
        
        Set IP_RegExp = Nothing
    
    End If
    
End Function

对于 IPv6,我使用 MySQL 来计算数值。这是一个简单的 SELECT 示例:

SELECT CAST(
    CONV(
        SUBSTR(
            HEX(
                INET6_ATON('2a00:85c0:0001:0000:0000:0000:0241:0023')
            ),1,16),16,10
)AS DECIMAL(65))
*18446744073709551616
+CAST(
    CONV(
        SUBSTR(
            HEX(
                INET6_ATON('2a00:85c0:0001:0000:0000:0000:0241:0023')
            ),17,10
) AS DECIMAL(65)) AS ipv6_num;

输出:55830288595252163998698714105846497315(使用完整或缩短的 IPv6 地址)

它也适用于 MariaDB。对于其他 SQL 平台,逻辑相同,但语法和函数可能需要替换为等效项。

如果您出于地理定位的目的记录 IP 数值,显然您使用的是数据库,因此将上述 MySQL 代码调整为其他 SQL 平台是我能提供的最佳解决方案。

我还查找了数字 API 的 IP(免费或基于订阅),但似乎没有(IPv6 仍然非常罕见,因此 REST API 调用可能是一个可能的解决方案)。希望有一个使用 JScript 的解决方案,或者如前所述,您可以使用 COM DLL(我有这方面的经验,我已经使用 C# 创建了许多 COM DLL,用于我的 GitHub page 上的经典 ASP 应用程序。不过,您将需要 root 访问权限。我使用的是新笔记本电脑,因此需要重新安装 Visual Studio,但我会在有时间时为 IP 创建一个 COM DLL 到数值)。