MySQL depolama için ikili IPv6 dönüştürmek için nasıl

2 Cevap php

Ben verimli bir şekilde MySQL 5.0 IPv6 adreslerini saklamak için çalışıyorum. Bu konuyla ilgili diğer soruları, such as this one okudum. Bu soruya yazarı sonunda iki BIGINT alanlar için seçti. IPv6 adresi saklamak için bir DECIMAL (39,0) kullanarak: Benim aramalarda da bir başka sık kullanılan mekanizma yukarı döndü. Ben bu konuda iki soru var.

  1. Örneğin 2 * BIGINT gibi diğer yöntemlere göre DECIMAL (39,0) kullanmanın avantajları ve dezavantajları nelerdir?
  2. MySQL ile kullanılabilen bir ondalık dize biçime inet_pton() tarafından döndü ve nasıl güzel-baskı inet_ntop I can yüzden geri dönüştürmek () yok gibi nasıl ikili biçimi (PHP) dönüştürebilirim?

2 Cevap

İşte şimdi (39,0) biçiminde ve DECIMAL IP adreslerine dönüştürmek için kullanabileceğiniz işlevleri vardır. Onlar, "sunum-to-ondalık" ve "ondalık-to-sunum" için inet_ptod ve inet_dtop adlandırılır. Bu IPv6 ve PHP BCMath desteğe ihtiyacı vardır.

/**
 * 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;
}

Biz bunun yerine VARBINARY(16) sütun için gitti ve dönüşümleri yapmak için inet_pton() and inet_ntop() kullanın:

https://bitbucket.org/skion/mysql-udf-ipv6

Fonksiyonları çalışan bir MySQL sunucusuna yüklenebilir ve sadece INET_NTOA tanıdık ve {[(3)] olarak, SQL size INET6_NTOP ve INET6_PTON verecek IPv4 için} fonksiyonlar.

Düzenleme: Uyumlu fonksiyonlar sadece, şimdi MySQL vardır different names. Önceden 5.6 MySQL ve yükseltme yolu uygun bir gelecek arayan Yalnızca yukarıdaki kullanın.