小心,開頭為 0 的位址會回傳 false。
範例
<?php
inet_pton('172.27.1.04'); // 回傳 false
inet_pton('172.27.1.4') ;// 回傳正確的結果
?>
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
inet_pton — 將人類可讀的 IP 位址轉換為其壓縮的 in_addr 表示法
此函式將人類可讀的 IPv4 或 IPv6 位址(如果 PHP 使用 IPv6 支援編譯)轉換為適當的 32 位元或 128 位元二進制結構。
ip
人類可讀的 IPv4 或 IPv6 位址。
回傳給定 ip
的 in_addr
表示法,如果給定的 ip
語法無效(例如,沒有點號的 IPv4 位址或沒有冒號的 IPv6 位址),則回傳 false
。
範例 #1 inet_pton() 範例
<?php
$in_addr = inet_pton('127.0.0.1');
$in6_addr = inet_pton('::1');
?>
小心,開頭為 0 的位址會回傳 false。
範例
<?php
inet_pton('172.27.1.04'); // 回傳 false
inet_pton('172.27.1.4') ;// 回傳正確的結果
?>
如果您想使用上述函式,您應該先測試 ':' 字元,再測試 '.' 字元。意思是,您應該先檢查它是否為 IPv6 位址,再檢查是否為 IPv4 位址。
為什麼? IPv6 允許這種表示法
::127.0.0.1
如果您檢查 '.' 字元,您會認為這是 IPv4 位址,並且它會失敗。
可以透過 AF_INET6 常數來驗證 PHP 是否使用 --disable-ipv6 選項編譯。
<?php
if (defined('AF_INET6')) {
echo "PHP 編譯時沒有使用 --disable-ipv6 選項";
} else {
echo "PHP 編譯時使用了 --disable-ipv6 選項";
}
?>
關於 ::127.0.0.1 表示法
這是一個非常特殊的案例,不需要處理。這種表示法是保留給 IPv4 相容的 IPv6 位址的。
例如,::ffff:192.0.2.128 的表示法可以很容易地讀作「對應到 IPv4 位址 192.0.2.128 的 IPv6 位址」
然而,正如 RFC 所說
https://tools.ietf.org/html/rfc5156#page-2
2.2. IPv4 對應位址
::FFFF:0:0/96 是 IPv4 對應位址 [RFC4291]。這些位址
不應出現在公共網際網路上。
2.3. IPv4 相容位址
::<ipv4-address>/96 是 IPv4 相容位址 [RFC4291]。
這些位址已被棄用,不應出現在公開的
網際網路上。
這表示只有在需要與私人 IP 相容時才需要處理這種表示法。
如果輸入字串不是可讀的 IP 位址,inet_pton() 會產生 E_WARNING 並返回 FALSE。inet_ntop() 也是如此。
此外,inet_pton() 不識別輸入字串中的網路遮罩表示法(例如:「1.2.3.4/24」或「1:2::3:4/64」)。這與某些資料庫系統(如 PostgreSQL)支援 IP 位址類型的做法不同,因此如果您在 PHP 中處理 IP 位址時需要這種功能,則必須自行撰寫。
一個粗略的例子
<?php
// Sample IP addresses
$ipaddr = '1.2.3.4/24'; // IPv4 with /24 netmask
$ipaddr = '1:2::3:4/64'; // IPv6 with /64 netmask
// Strip out the netmask, if there is one.
$cx = strpos($ipaddr, '/');
if ($cx)
{
$subnet = (int)(substr($ipaddr, $cx+1));
$ipaddr = substr($ipaddr, 0, $cx);
}
else $subnet = null; // No netmask present
// Convert address to packed format
$addr = inet_pton($ipaddr);
// Let's display it as hexadecimal format
foreach(str_split($addr) as $char) echo str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
echo "<br />\n";
// Convert the netmask
if (is_integer($subnet))
{
// Maximum netmask length = same as packed address
$len = 8*strlen($addr);
if ($subnet > $len) $subnet = $len;
// Create a hex expression of the subnet mask
$mask = str_repeat('f', $subnet>>2);
switch($subnet & 3)
{
case 3: $mask .= 'e'; break;
case 2: $mask .= 'c'; break;
case 1: $mask .= '8'; break;
}
$mask = str_pad($mask, $len>>2, '0');
// Packed representation of netmask
$mask = pack('H*', $mask);
}
// Display the netmask as hexadecimal
foreach(str_split($mask) as $char) echo str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
?>
如果您收到 IPv6 位址的「無法識別的位址」錯誤,則可能是您的 PHP 版本未編譯 IPv6 支援。
要檢查,請載入 phpinfo(); 並查看「IPv6 支援」是否設定為「已停用」。