inet_pton

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

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

描述

inet_pton(string $ip): string|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() - 将打包的互联网地址转换为可读表示形式

添加说明

用户贡献说明 8 个说明

TuRn3r
10 年前
小心,以 0 开头的地址返回 false。

示例
<?php
inet_pton
('172.27.1.04'); // 返回 false
inet_pton('172.27.1.4') ;// 返回正确的结果
?>
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 兼容,则只需要处理这种表示法。
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 选项编译";
}

?>
strata_ranger at hotmail dot com
14 年前
如果输入字符串不是可读的 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'; // IPv4 带 /24 子网掩码
$ipaddr = '1:2::3:4/64'; // IPv6 带 /64 子网掩码

// 如果存在,则剥离子网掩码。
$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 支持”是否设置为“已禁用”。
tobias
8 年前
天啊

0000:0000:0000:0000:0000:0000:0127:2258
变成 '"X.

不要忘记对其进行转义
eric at vyncke org
17 年前
在下面的函数中并不容易... 它没有处理 '::' 的情况,这种情况可能发生在 IPv6 中,它代表任何数量的 0,地址可以像 ff05::1 那样简单
To Top