Sander Steffann在我之前的问题中提到:
像000000000000000000000000000000000000:192.168.0.1这样的地址被写成000000000000000000000000000000000000000:c0a8:0001这是完全相同的地址但在十六进制表示法中
如何在PHP中检测一个地址是否被写成eg。: ::0000:192.168.0.1
或0000::0000:192.168.0.1
或0000:0000:0000:0000:0000:0000:192.168.0.1
等?检查基于ip的字符串是否有'。'是否足够?AND
我如何将其更改为完整字符串0000:0000:0000:0000:0000:0000:c0a8:0001
?
我是正确的,将其更改为IPv4将是这样的:
<?php
$strIP = '0000:0000:0000:0000:0000:0000:192.168.0.1';
$strResult = substr($strIP, strrpos($strIP, ':'));
echo $strResult; //192.168.0.1 ?
?>
…还是正确的IP字符串表示比这个代码段所能做的更复杂?
我简直不敢相信我一口气写完这些,而且第一次就成功了。
$strIP = '0000:0000:0000:0000:0000:0000:192.168.0.1';
$arrIP = explode(':', $strIP);
if( preg_match('/^'d{1,3}'.'d{1,3}'.'d{1,3}'.'d{1,3}$/', $arrIP[count($arrIP)-1]) ) {
$ip4parts = explode('.', $arrIP[count($arrIP)-1]);
$ip6trans = sprintf("%02x%02x:%02x%02x", $ip4parts[0], $ip4parts[1], $ip4parts[2], $ip4parts[3]);
$arrIP[count($arrIP)-1] = $ip6trans;
$strIP = implode(':', $arrIP);
}
echo $strIP; //output: 0000:0000:0000:0000:0000:0000:c0a8:0001
基本上:
- 在
:
上爆炸字符串 - 检查最后一个quad是否格式化为IP4地址
- 在
.
上引爆最后一个quad - 将IP4八位元重新打印成两个十六进制四边形
- 用新的IP4四元组替换IP4四元组
- 在
:
上内爆数组
您最好不要手动执行此操作,而是调用inet_pton
以获得二进制表示,然后将其转换为您希望拥有的格式。
$foo = inet_pton("::1");
for ($i = 0 ; $i < 8 ; $i++)
$arr[$i] = sprintf("%02x%02x", ord($foo[$i * 2]), ord($foo[$i * 2 + 1]));
$addr = implode(":", $arr);
首先:你为什么要关心地址是怎么写的呢?Inet_pton()将为您解析所有变量并给出一致的结果,然后您可以将其转换为二进制,十六进制或任何您想要的。
将::192.168.0.1
转换为0000:0000:0000:0000:0000:0000:c0a8:0001
的所有代码实际上都在我的帖子中。这正是我的示例函数所做的。
如果您将0000:0000:0000:0000:0000:0000:192.168.0.1
提供给inet_pton(),然后再提供给inet_ntop(),您将获得规范的IPv6符号,在这种情况下是::192.168.0.1
。如果该字符串以::
开头,其余部分不包含:
和三个点,那么您可以非常确定它是IPv4地址;-)
把你上一个问题的答案和这个问题结合起来:
function expand_ip_address($addr_str) {
/* First convert to binary, which also does syntax checking */
$addr_bin = @inet_pton($addr_str);
if ($addr_bin === FALSE) {
return FALSE;
}
$addr_hex = bin2hex($addr_bin);
/* See if this is an IPv4-Compatible IPv6 address (deprecated) or an
IPv4-Mapped IPv6 Address (used when IPv4 connections are mapped to
an IPv6 sockets and convert it to a normal IPv4 address */
if (strlen($addr_bin) == 16
&& substr($addr_hex, 0, 20) == str_repeat('0', 20)) {
/* First 80 bits are zero: now see if bits 81-96 are either all 0 or all 1 */
if (substr($addr_hex, 20, 4) == '0000')
|| substr($addr_hex, 20, 4) == 'ffff')) {
/* Remove leading bits so only the IPv4 bits remain */
$addr_bin = substr($addr_hex, 12);
}
}
/* Then differentiate between IPv4 and IPv6 */
if (strlen($addr_bin) == 4) {
/* IPv4: print each byte as 3 digits and add dots between them */
$ipv4_bytes = str_split($addr_bin);
$ipv4_ints = array_map('ord', $ipv4_bytes);
return vsprintf('%03d.%03d.%03d.%03d', $ipv4_ints);
} else {
/* IPv6: print as hex and add colons between each group of 4 hex digits */
return implode(':', str_split($addr_hex, 4));
}
}