首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >INET_ATON()和INET_NTOA()?

INET_ATON()和INET_NTOA()?
EN

Stack Overflow用户
提问于 2010-05-03 01:45:05
回答 6查看 54.3K关注 0票数 34

我希望将IP地址存储在我的数据库中,但我还需要在整个应用程序中使用它们。我读到过在MySQL查询中使用INET_ATON()INET_NTOA()从IP地址中获取32位无符号整数,这正是我想要的,因为它将使整个数据库的搜索速度比使用char(15)更快。

问题是,我找不到一个在PHP中做同样事情的函数。我唯一遇到的就是:

http://php.net/manual/en/function.ip2long.php

所以我测试了一下:

代码语言:javascript
复制
$ip = $_SERVER['REMOTE_ADDR'];
echo ip2long($ip);

而且它什么也不会输出。在他们给出的示例中,它似乎是有效的,但我也不确定ip2long()是否做了与INET_ATON()相同的事情。

有没有人知道PHP函数可以做到这一点?或者甚至是在数据库中存储IP地址的全新解决方案?

谢谢。

EN

回答 6

Stack Overflow用户

发布于 2010-05-03 01:48:39

和函数应该工作得很好。

注意:您应该将它们用于IPv4地址--在您的示例中,请确保$_SERVER['REMOTE_ADDR']实际上包含一个有效的IPv4地址(而不是一些ipv6内容)。

尝试使用google IP地址:

代码语言:javascript
复制
var_dump(ip2long('209.85.227.147'));
var_dump(long2ip(3512066963));

我得到以下输出:

代码语言:javascript
复制
int(3512066963)
string(14) "209.85.227.147" 
票数 36
EN

Stack Overflow用户

发布于 2011-09-06 04:55:14

ip2longlong2ip和MySQL函数之间有一个重要的区别。

PHP的ip2longlong2ip处理有符号整数。

请参阅http://php.net/manual/en/function.ip2long.php

“由于PHP的整数类型是有符号的,并且许多IP地址在32位体系结构上会导致负整数,因此您需要使用sprintf()或printf()的'%u‘格式化程序来获取无符号IP地址的字符串表示。”

MySQL的INET_ATON()INET_NTOA()处理无符号整数

请参阅http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton

“要存储由INET_ATON()生成的值,请使用INT UNSIGNED列,而不是INT,因为INT是有符号的。如果使用signed列,则无法正确存储第一个八位字节大于127的IP地址的值。”

这里有一些你可以用来在两者之间工作的函数。

如果您使用INET_ATON()将IP插入到MySQL数据库中,则可以使用以下命令将其转换回PHP语言:

代码语言:javascript
复制
long2ip(sprintf("%d", $ip_address));

您可以使用以下代码将其从PHP转换为保存在数据库中:

代码语言:javascript
复制
sprintf("%u", ip2long($ip_address));

(同样重要的是,不要将$ip_address类型转换为int,因为如果它大于MAX_INT,则包装数字可能会导致问题。如果必须强制转换,请将其转换为longfloat)

票数 35
EN

Stack Overflow用户

发布于 2013-03-13 04:18:17

你不应该在PHP中处理这个问题,这就是MySQL原生函数的作用。请参阅此示例:

代码语言:javascript
复制
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 |
+----------+------------------+

如果您希望在同一字段中同时处理ipv4和ipv6,并且使用的是MySQL5.6或更高版本,则可以使用varbinary(16)以及函数inet6_aton和inet6_ntoa。这是一个更好的例子,说明了为什么应该使用MySQL函数,而不是在PHP中处理二进制数据:

代码语言:javascript
复制
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      |
| ¦Ç      ??¦ ¦?â) | 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 |
+--------------------------+---------------------------------+

您可以看到,通过这样做,您实际上可以避免计算不同格式的ipv6地址,因为MySQL会将它们转换为二进制,然后再转换回最简单的表达式。

我知道这个问题已经有两年多了,但我想让这个信息对其他遇到的人有用。

HTH

弗朗西斯科·扎拉博佐

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2754340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档