PHP 中的 INET_ATON() 和 INET_NTOA()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/2754340/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
INET_ATON() and INET_NTOA() in PHP?
提问by blerh
I want to store IP addresses in my database, but I also need to use them throughout my application. I read about using INET_ATON()and INET_NTOA()in my MySQL queries to get a 32-bit unsigned integer out of an IP address, which is exactly what I want as it will make searching through the database faster than using char(15).
我想在我的数据库中存储 IP 地址,但我还需要在整个应用程序中使用它们。我阅读了有关使用INET_ATON()和INET_NTOA()在我的 MySQL 查询中从 IP 地址中获取 32 位无符号整数的信息,这正是我想要的,因为它可以比使用 char(15) 更快地搜索数据库。
The thing is, I can't find a function that does the same sort of thing in PHP. The only thing I came across is:
问题是,我找不到在 PHP 中做同样事情的函数。我遇到的唯一一件事是:
http://php.net/manual/en/function.ip2long.php
http://php.net/manual/en/function.ip2long.php
So I tested it:
所以我测试了一下:
$ip = $_SERVER['REMOTE_ADDR'];
echo ip2long($ip);
And it outputs nothing. In the example they gave it seems to work, but then again I'm not exactly sure if ip2long()does the same thing as INET_ATON().
它什么都不输出。在他们给出的示例中,它似乎有效,但我又不确定是否ip2long()与INET_ATON().
Does someone know a PHP function that will do this? Or even a completely new solution to storing an IP address in a database?
有人知道可以执行此操作的 PHP 函数吗?或者甚至是在数据库中存储 IP 地址的全新解决方案?
Thanks.
谢谢。
回答by Pascal MARTIN
The ip2long()and long2ip()functions should work just fine.
Note : you should use those for IPv4 addresses -- make sure that, in your case, $_SERVER['REMOTE_ADDR']actually contains a valid IPv4 address (and not some IPv6-stuff).
注意:您应该将这些用于 IPv4 地址——确保在您的情况下,$_SERVER['REMOTE_ADDR']实际上包含一个有效的 IPv4 地址(而不是一些 IPv6 的东西)。
Trying on a google IP address :
尝试使用谷歌 IP 地址:
var_dump(ip2long('209.85.227.147'));
var_dump(long2ip(3512066963));
I get the following output :
我得到以下输出:
int(3512066963)
string(14) "209.85.227.147" 
回答by Tom
There is an important distinction between ip2long, long2ipand the MySQL functions.
有一个重要区别ip2long,long2ip和MySQL的功能。
PHP's ip2longand long2ipdeal with signed integers.
PHPip2long和long2ip处理有符号整数。
See http://php.net/manual/en/function.ip2long.php
见http://php.net/manual/en/function.ip2long.php
"Because PHP's integer type is signed, and many IP addresses will result in negative integers on 32-bit architectures, you need to use the '%u' formatter of sprintf() or printf() to get the string representation of the unsigned IP address."
"因为PHP的整数类型是有符号的,而很多IP地址在32位架构上会产生负整数,所以需要使用sprintf()或printf()的'%u'格式化程序来获取无符号IP的字符串表示地址。”
MySQL's INET_ATON()and INET_NTOA()deal with unsigned integers
MySQLINET_ATON()和INET_NTOA()处理无符号整数
See http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton
见http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton
"To store values generated by INET_ATON(), use an INT UNSIGNED column rather than INT, which is signed. If you use a signed column, values corresponding to IP addresses for which the first octet is greater than 127 cannot be stored correctly."
“要存储由 INET_ATON() 生成的值,请使用 INT UNSIGNED 列而不是带符号的 INT。如果使用带符号的列,则无法正确存储与第一个八位字节大于 127 的 IP 地址对应的值。”
Here are some functions you can use to work between the two.
以下是一些可用于在两者之间工作的函数。
If you inserted into the MySQL database, an IP using INET_ATON(), you can convert it back in PHP using the following:
如果您使用INET_ATON()将IP 插入 MySQL 数据库,则可以使用以下命令将其转换回 PHP:
long2ip(sprintf("%d", $ip_address));
And you can convert it to save it in the database from PHP using this:
您可以使用以下命令将其转换为从 PHP 保存在数据库中:
sprintf("%u", ip2long($ip_address));
(Also important, don't type-cast the $ip_addressto intas this might cause problems by wrapping the number if it's bigger than MAX_INT. If you must cast it, cast it to a longor float)
(同样重要的是,不要将 the 类型$ip_address转换int为to因为如果数字大于 ,则可能会通过包装数字而导致问题MAX_INT。如果必须转换它,请将其转换为 along或float)
回答by Francisco Zarabozo
You should not have to deal with that inside PHP, that's what MySQL native funcions are for. See this example:
您不应该在 PHP 内部处理它,这就是 MySQL 本机函数的用途。看这个例子:
create table iptable (
    ip int(32) unsigned not null,
    comment varchar(32) not null
);
insert into iptable (ip, comment) values (inet_aton('10.0.0.3'), 'This is 10.0.0.3');
select * from iptable;
+-----------+------------------+
| ip        | comment          |
+-----------+------------------+
| 167772163 | This is 10.0.0.3 |
+-----------+------------------+
select inet_ntoa(ip) as ip, comment from iptable;
+----------+------------------+
| ip       | comment          |
+----------+------------------+
| 10.0.0.3 | This is 10.0.0.3 |
+----------+------------------+
If you want to deal with both ipv4 and ipv6 in the same field, and you are using Mysql 5.6 or higher, you can use varbinary(16) and the functions inet6_aton and inet6_ntoa. This is a better example of why you should use MySQL functions and not deal with binary data inside PHP:
如果你想在同一个领域同时处理 ipv4 和 ipv6,并且你使用的是 Mysql 5.6 或更高版本,你可以使用 varbinary(16) 和函数 inet6_aton 和 inet6_ntoa。这是一个更好的例子,说明为什么应该使用 MySQL 函数而不是在 PHP 中处理二进制数据:
create table iptable2 (
    ip varbinary(16) not null,
    comment varchar(32) not null
);
insert into iptable2 (ip, comment) values
    (inet6_aton('192.168.1.254'), 'This is router 192.168.1.254'),
    (inet6_aton('::1'), 'This is ipv6 localhost ::1'),
    (inet6_aton('FE80:0000:0000:0000:0202:B3FF:FE1E:8329'), 'This is some large ipv6 example')
;
select * from iptable2;
+------------------+---------------------------------+
| ip               | comment                         |
+------------------+---------------------------------+
| +??|             | This is router 192.168.1.254    |
|                ? | This is ipv6 localhost ::1      |
| |?      ??|?|?a) | This is some large ipv6 example |
+------------------+---------------------------------+
select inet6_ntoa(ip) as ip, comment from iptable2;
+--------------------------+---------------------------------+
| ip                       | comment                         |
+--------------------------+---------------------------------+
| 192.168.1.254            | This is router 192.168.1.254    |
| ::1                      | This is ipv6 localhost ::1      |
| fe80::202:b3ff:fe1e:8329 | This is some large ipv6 example |
+--------------------------+---------------------------------+
You can see that by doing this, you can actually avoid having to evaluate ipv6 addresses in different formats, since MySQL converts them to binary and back to their simpliest expression.
您可以看到,通过这样做,您实际上可以避免必须以不同格式计算 ipv6 地址,因为 MySQL 将它们转换为二进制并返回到它们最简单的表达式。
I know this question has more than 2 years already, but I want to let this information be useful for others that come across.
我知道这个问题已经超过 2 年了,但我想让这些信息对遇到的其他人有用。
HTH
HTH
Francisco Zarabozo
弗朗西斯科·萨拉博佐
回答by Alix Axel
For IPv4 and IPv6 support use inet_pton()and inet_ntop(), these are availiable since PHP 5.1+ and mimic exactly the equivalent MySQL functions.
对于 IPv4 和 IPv6 支持使用inet_pton()和inet_ntop(),这些自 PHP 5.1+ 起可用,并且完全模仿等效的 MySQL 函数。
Otherwise just use ip2long()and long2ip().
否则只需使用ip2long()和long2ip()。
回答by user2253362
Here PHP alternative functions (simple copy/paste in your program) -
这里 PHP 替代函数(在程序中简单复制/粘贴)-
function inet_aton($ip)
{
    $ip = trim($ip);
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) return 0;
    return sprintf("%u", ip2long($ip));  
}
function inet_ntoa($num)
{
    $num = trim($num);
    if ($num == "0") return "0.0.0.0";
    return long2ip(-(4294967295 - ($num - 1))); 
}
回答by ZZ Coder
ip2long is equivalent to inet_aton().
ip2long 相当于 inet_aton()。
ip2long only works with IPv4. I suspect your system is using IPv6 for loopback. Try to print REMOTE_ADDR.
ip2long 仅适用于 IPv4。我怀疑您的系统正在使用 IPv6 进行环回。尝试打印 REMOTE_ADDR。

