如何从二进制转换IPv6以存储在MySQL中

我正在尝试以有效的方式将IPv6地址存储在MySQL

5.0中。我已经阅读了与此相关的其他问题,例如这个。该问题的作者最终选择了两个BIGINT字段。我的搜索还发现了另一个常用的机制:使用DECIMAL(39,0)存储IPv6地址。我对此有两个问题。

  1. 与其他方法(例如2 * BIGINT)相比,使用DECIMAL(39,0)有什么优缺点?
  2. 如何将inet_pton()返回的二进制格式(在PHP中)转换为MySQL可用的十进制字符串格式,以及如何转换回以使inet_ntop()漂亮打印?

回答:

这是我现在用来将IP地址与DECIMAL(39,0)格式之间相互转换的函数。它们分别被命名为inet_ptod和inet_dtop,以表示“十进制表示”和“十进制表示”。它需要PHP中的IPv6和bcmath支持。

/**

* Convert an IP address from presentation to decimal(39,0) format suitable for storage in MySQL

*

* @param string $ip_address An IP address in IPv4, IPv6 or decimal notation

* @return string The IP address in decimal notation

*/

function inet_ptod($ip_address)

{

// IPv4 address

if (strpos($ip_address, ':') === false && strpos($ip_address, '.') !== false) {

$ip_address = '::' . $ip_address;

}

// IPv6 address

if (strpos($ip_address, ':') !== false) {

$network = inet_pton($ip_address);

$parts = unpack('N*', $network);

foreach ($parts as &$part) {

if ($part < 0) {

$part = bcadd((string) $part, '4294967296');

}

if (!is_string($part)) {

$part = (string) $part;

}

}

$decimal = $parts[4];

$decimal = bcadd($decimal, bcmul($parts[3], '4294967296'));

$decimal = bcadd($decimal, bcmul($parts[2], '18446744073709551616'));

$decimal = bcadd($decimal, bcmul($parts[1], '79228162514264337593543950336'));

return $decimal;

}

// Decimal address

return $ip_address;

}

/**

* Convert an IP address from decimal format to presentation format

*

* @param string $decimal An IP address in IPv4, IPv6 or decimal notation

* @return string The IP address in presentation format

*/

function inet_dtop($decimal)

{

// IPv4 or IPv6 format

if (strpos($decimal, ':') !== false || strpos($decimal, '.') !== false) {

return $decimal;

}

// Decimal format

$parts = array();

$parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0);

$decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336'));

$parts[2] = bcdiv($decimal, '18446744073709551616', 0);

$decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616'));

$parts[3] = bcdiv($decimal, '4294967296', 0);

$decimal = bcsub($decimal, bcmul($parts[3], '4294967296'));

$parts[4] = $decimal;

foreach ($parts as &$part) {

if (bccomp($part, '2147483647') == 1) {

$part = bcsub($part, '4294967296');

}

$part = (int) $part;

}

$network = pack('N4', $parts[1], $parts[2], $parts[3], $parts[4]);

$ip_address = inet_ntop($network);

// Turn IPv6 to IPv4 if it's IPv4

if (preg_match('/^::\d+.\d+.\d+.\d+$/', $ip_address)) {

return substr($ip_address, 2);

}

return $ip_address;

}

以上是 如何从二进制转换IPv6以存储在MySQL中 的全部内容, 来源链接: utcz.com/qa/399545.html

回到顶部