PHP 大会日本 2024

inet_pton

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

inet_pton将人类可读的 IP 地址转换为其打包的 in_addr 表示形式

描述

inet_pton(字符串 $ip): 字符串|false

此函数将人类可读的 IPv4 或 IPv6 地址(如果 PHP 构建时启用了 IPv6 支持)转换为适合地址族的 32 位或 128 位二进制结构。

参数

ip

人类可读的 IPv4 或 IPv6 地址。

返回值

返回给定 ipin_addr 表示形式,或者如果给定语法无效的 ip(例如,没有点的 IPv4 地址或没有冒号的 IPv6 地址),则返回 false

示例

示例 #1 inet_pton() 示例

<?php
$in_addr
= inet_pton('127.0.0.1');

$in6_addr = inet_pton('::1');
?>

参见

  • ip2long() - 将包含 (IPv4) 互联网协议点分地址的字符串转换为长整数
  • long2ip() - 将长整数地址转换为 (IPv4) 互联网标准点分格式的字符串
  • inet_ntop() - 将打包的互联网地址转换为人类可读的表示形式

添加注释

用户贡献的注释 6 条注释

TuRn3r
10 年前
小心,带有前导 0 的地址返回 false。

示例
<?php
inet_pton
('172.27.1.04'); // 返回 false
inet_pton('172.27.1.4') ;// 返回正确的结果
?>
me at diogoresende dot net
18 年前
如果您想使用上述函数,则应在 '.' 之前测试 ':' 字符。这意味着,您应该在检查 IPv4 之前检查它是否为 IPv6 地址。
为什么?IPv6 允许这种类型的表示法

::127.0.0.1

如果您检查 '.' 字符,您会认为这是一个 IPv4 地址,并且它将失败。
francis dot besset at gmail dot com
13 年前
可以通过 AF_INET6 常量验证 PHP 是否使用 --disable-ipv6 选项编译。

<?php

if (defined('AF_INET6')) {
echo
"PHP 未使用 --disable-ipv6 选项编译";
} else {
echo
"PHP 使用 --disable-ipv6 选项编译";
}

?>
admin at hanzlsoft dot eu
3 年前
关于 ::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 兼容时处理这种类型的表示法
strata_ranger at hotmail dot com
15 年前
如果输入字符串不是可读的 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

// 示例 IP 地址
$ipaddr = '1.2.3.4/24'; // 带 /24 子网掩码的 IPv4
$ipaddr = '1:2::3:4/64'; // 带 /64 子网掩码的 IPv6

// 如果存在子网掩码,则将其去除。
$cx = strpos($ipaddr, '/');
if (
$cx)
{
$subnet = (int)(substr($ipaddr, $cx+1));
$ipaddr = substr($ipaddr, 0, $cx);
}
else
$subnet = null; // 没有子网掩码

// 将地址转换为打包格式
$addr = inet_pton($ipaddr);

// 以十六进制格式显示
foreach(str_split($addr) as $char) echo str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
echo
"<br />\n";

// 转换子网掩码
if (is_integer($subnet))
{
// 最大子网掩码长度 = 打包地址的长度
$len = 8*strlen($addr);
if (
$subnet > $len) $subnet = $len;

// 创建子网掩码的十六进制表达式
$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');

// 子网掩码的打包表示
$mask = pack('H*', $mask);
}

// 以十六进制显示子网掩码
foreach(str_split($mask) as $char) echo str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);

?>
dave at php dot net
9 年前
如果您收到 IPv6 地址的“无法识别的地址”错误,则可能是您的 PHP 版本未编译为支持 IPv6。

要检查,请加载 phpinfo(); 并查看“IPv6 支持”是否设置为“已禁用”。
To Top