加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > PHP > 正文

PHP中有关IPV4 和IPV6地址转换以及其它一些常见问题

发布时间:2020-05-25 02:56:06 所属栏目:PHP 来源:互联网
导读:这里主要介绍一下 IPV4 / IPV6 在 PHP / MySQL 中如何转换。以及中间容易碰到的一些问题。 首先介绍两个函数: ip2long:将 IPV4 的字符串互联网协议转换成长整型数字 l

这里主要介绍一下 IPV4 / IPV6 在 PHP / MySQL 中如何转换。以及中间容易碰到的一些问题。

  • 首先介绍两个函数:

ip2long:将 IPV4 的字符串互联网协议转换成长整型数字

int ( )

long2ip:将长整型转化为字符串形式带点的互联网标准格式地址(IPV4)

( int )

问题一:MySQL 中如何存储IP地址。

  • IPV4 地址长度32位,有 2^32-1 个地址。 所以 MySQL 中如果使用 int 来存储,要加 unsigned 标识。
  • int 有符号的范围是 -2^31 (-2,147,483,648) 到 2^31 - 1 (2,647) ,无符号的范围是 0 到 2^32-1(4294967295)
  • IPV6 地址长度128位。因此不能使用 int 存储,可以使用 varchar 类型存储。

问题二:ip2long 出现负数问题。

示例:

= ('192.168.8.30' = ( ; ;

查看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的 integer 类型是有符号,并且有许多的IP地址将导致在32位系统的情况下为负数, 你需要使用 “%u” 进行转换通过 sprintf() 或printf() 得到的字符串来表示无符号的IP地址。

解决办法:

= ('%u',('192.168.8.30' ;

接着又发现一个新问题,如果是通过 “%u” 进行转换后再调用 long2ip,会提示错误:

long2ip() expects parameter 1 to be integer,string given

接着查手册,PHP手册上是这么介绍的:

On 32-bit architectures,casting integer representations of IP addresses from string to integer is not suppossed to give correct results for numbers which exceed PHP_INT_MAX.在 32 位架构中,从 string 转换 integer 整型形式的 ip 地址将有可能导致错误的结果,因为结果数字超出了 PHP_INT_MAX 限制。

最终解决办法,封装两个方法:

convertIpToString( = 4294967295 - ( - 1 (-<span style="color: #008000">/<span style="color: #008000">

  • 代替 ip2long 函数
  • @param $ip
  • @return string
    <span style="color: #008000">*/
    <span style="color: #0000ff">function convertIpToLong(<span style="color: #800080">$ip<span style="color: #000000">)
    {
    <span style="color: #0000ff">return <span style="color: #008080">sprintf("%u",<span style="color: #008080">ip2long(<span style="color: #800080">$ip<span style="color: #000000">));
    }

    测试调用:

    = ->convertIpToLong('192.168.8.30' = ->convertIpToString(

<span style="color: #0000ff">echo <span style="color: #800080">$ip_long; <span style="color: #008000">//<span style="color: #008000"> 3232237598
<span style="color: #0000ff">echo <span style="color: #800080">$long_ip; <span style="color: #008000">//<span style="color: #008000"> 192.168.8.30

问题三:MySQL 中怎么转换 IP 地址。

  • MySQL 中提供了几个函数,INET_ATON 将 IPV4 地址转换为整数。 INET_NTOA 将整数转换为 IPV4 地址。
  • 如果是 IPV6 地址也有对应的方法:INET6_ATON 和 INET6_NTOA,这两个方法需要 5.6 以上版本才能使用。

调用示例:

SELECT INET_ATON('192.168.8.30'); SELECT INET_NTOA('3232237598');

问题四:PHP 中怎么处理 IPV6 地址。

  • PHP 中没有直接提供函数实现 IPV6 地址的转换。 不过PHP手册中提供了两个方法可以实现这一需求。要运行这两个方法首先需要开启 php_gmp.dll 模块。
ip2long6( = inet_pton( = 15; = '' ( >= 0 = ("%08b",(([ = . -- gmp_strval(gmp_init(,2),10<span style="color: #008000">/<span style="color: #008000">

  • 整数转换为 IPV6 地址

  • @param $ipv6long

  • @return string
    <span style="color: #008000">*/
    <span style="color: #0000ff">function long2ip6(<span style="color: #800080">$ipv6long<span style="color: #000000">)
    {

    <span style="color: #800080">$bin = gmp_strval(gmp_init(<span style="color: #800080">$ipv6long,10),2<span style="color: #000000">);
    <span style="color: #0000ff">if (<span style="color: #008080">strlen(<span style="color: #800080">$bin) < 128<span style="color: #000000">) {
    <span style="color: #800080">$pad = 128 - <span style="color: #008080">strlen(<span style="color: #800080">$bin<span style="color: #000000">);
    <span style="color: #0000ff">for (<span style="color: #800080">$i = 1; <span style="color: #800080">$i <= <span style="color: #800080">$pad; <span style="color: #800080">$i++<span style="color: #000000">) {
    <span style="color: #800080">$bin = "0" . <span style="color: #800080">$bin<span style="color: #000000">;
    }
    }
    <span style="color: #800080">$bits = 0<span style="color: #000000">;
    <span style="color: #800080">$ipv6 = ''<span style="color: #000000">;
    <span style="color: #0000ff">while (<span style="color: #800080">$bits <= 7<span style="color: #000000">) {
    <span style="color: #800080">$bin_part = <span style="color: #008080">substr(<span style="color: #800080">$bin,(<span style="color: #800080">$bits * 16),16<span style="color: #000000">);
    <span style="color: #800080">$ipv6 .= <span style="color: #008080">dechex(<span style="color: #008080">bindec(<span style="color: #800080">$bin_part)) . ":"<span style="color: #000000">;
    <span style="color: #800080">$bits++<span style="color: #000000">;
    }
    <span style="color: #008000">//<span style="color: #008000"> compress
    <span style="color: #0000ff">return inet_ntop(inet_pton(<span style="color: #008080">substr(<span style="color: #800080">$ipv6,-1<span style="color: #000000">)));
    }

    测试调用:

    = ->ip2long6('2001:4860:a005::68' = ->long2ip6( ; ;

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读