继this post后,我对搜索IPv6地址范围感兴趣 .
在IPv4下,我将能够确定ISP提供的起始和结束IP地址,并使用这些整数值作为范围界限,快速搜索数据库以查看数据库中的任何条目是否落入该范围 .
这将如何受到IPv6的影响? ISP仍然会像现在这样在范围内拥有IPv6地址吗?如果将IPv6地址存储为SQL Server数据库中的两个bigint,您将如何有效地搜索这些范围?
在范围内使用IP地址(IPv4和IPv6都不正确)是不正确的 . 对特定“范围”IP地址进行分组的正确方法是使用前缀(CIDR表示法)或掩码(过时,仅对IPv4有效,如果您尝试使用非连续掩码,则会发生精神错乱) .
有时您会看到使用IPv4范围的某人(有时甚至是应用程序,家庭路由器等),但这只是错误的方法 .
使用Classless Inter-Domain Routing (CIDR)你将有一个元组<Address,Prefix>,其中Address是一个128位无符号整数,Prefix是一个很小的(0..128)无符号整数 . 前缀表示地址的最高有效位数表示网络地址,其余128个前缀最低有效位表示该网络中的特定主机 .
因此,例如,2620:0:860:2 :: / 64(wikimedia.org)的IPv6“范围”表示来自2620:0:860:2 ::最高2620:0:860:2的所有主机: FFFF:FFFF:FFFF:FFFF .
您不应该使用两个“bigint”将这样的值存储在数据库中,而是在单个列中使用任何本机表示,除非您想让开发人员的生活成为一场噩梦 . 如果您的DBMS不支持这么大的整数,除了替换您的DBMS之外,我建议使用16字节长的固定大小的二进制数据列 .
使用适当支持IPv6地址的DBMS不是一个坏主意 . 以下是PostgreSQL版本8.3的示例:
mydb=> CREATE TABLE Networks (name TEXT, prefix INET); CREATE TABLE mydb=> INSERT INTO Networks VALUES ('Documentation', '2001:DB8::/32'); INSERT 0 1 mydb=> INSERT INTO Networks VALUES ('ULA', 'FC00::/7'); INSERT 0 1 mydb=> INSERT INTO Networks VALUES ('Orchid', '2001:10::/28'); INSERT 0 1 mydb=> SELECT * FROM Networks; name | prefix ---------------+--------------- Documentation | 2001:db8::/32 ULA | fc00::/7 Orchid | 2001:10::/28 (3 rows) mydb=> SELECT * FROM Networks WHERE '2001:DB8::dcaf:BAD' << prefix; name | prefix ---------------+--------------- Documentation | 2001:db8::/32 (1 row)
2 回答
在范围内使用IP地址(IPv4和IPv6都不正确)是不正确的 . 对特定“范围”IP地址进行分组的正确方法是使用前缀(CIDR表示法)或掩码(过时,仅对IPv4有效,如果您尝试使用非连续掩码,则会发生精神错乱) .
有时您会看到使用IPv4范围的某人(有时甚至是应用程序,家庭路由器等),但这只是错误的方法 .
使用Classless Inter-Domain Routing (CIDR)你将有一个元组<Address,Prefix>,其中Address是一个128位无符号整数,Prefix是一个很小的(0..128)无符号整数 . 前缀表示地址的最高有效位数表示网络地址,其余128个前缀最低有效位表示该网络中的特定主机 .
因此,例如,2620:0:860:2 :: / 64(wikimedia.org)的IPv6“范围”表示来自2620:0:860:2 ::最高2620:0:860:2的所有主机: FFFF:FFFF:FFFF:FFFF .
您不应该使用两个“bigint”将这样的值存储在数据库中,而是在单个列中使用任何本机表示,除非您想让开发人员的生活成为一场噩梦 . 如果您的DBMS不支持这么大的整数,除了替换您的DBMS之外,我建议使用16字节长的固定大小的二进制数据列 .
使用适当支持IPv6地址的DBMS不是一个坏主意 . 以下是PostgreSQL版本8.3的示例: