问题描述
出于地理定位的目的,我试图获取 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 到数值)。