我已经为IPv4做了“这个”;
$ip = '127.0.0.1'; // example
$ip = explode('.',$ip);
if( count($ip) != 4 ) $ip = array(0,0,0,0); // wrong ip format, default to 0.0.0.0
return chr($ip[0]) . chr($ip[1]) . chr($ip[2]) . chr($ip[3]);
我也需要为IPv6做以上操作。阅读IPv6规范,(我承认我没有阅读所有),我看到几个奇怪的(“例外”),如一组0可以压缩成双冒号:“ :0000:0000“=>”::“(如果我的理解是正确的)。 我还看到了如何在IPv6字符串中包含IPv4样式的字符串:0:0:0:0:0:0:127.0.0.1
让我们首先说我不知道从哪里开始。
感谢Alvaro,现在我有了一个inet_pton的纯PHP实现:
/**
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
* @link http://php.net/inet_pton
* @author Arpad Ray <arpad@php.net>
*/
function php_compat_inet_pton($address) {
$r = ip2long($address);
if ($r !== false && $r != -1) return pack('N', $r);
$delim_count = substr_count($address, ':');
if ($delim_count < 1 || $delim_count > 7) return false;
$r = explode(':', $address);
$rcount = count($r);
if (($doub = array_search('', $r, 1)) !== false) {
$length = (!$doub || $doub == $rcount - 1 ? 2 : 1);
array_splice($r, $doub, $length, array_fill(0, 8 + $length - $rcount, 0));
}
$r = array_map('hexdec', $r);
array_unshift($r, 'n*');
$r = call_user_func_array('pack', $r);
return $r;
}
问题是,我不太明白它在做什么。问题是,我不能只是使用这样的功能,因为(对于一件事)我知道它以不同于我正在做(或想要)的格式包装IP。
答案 0 :(得分:3)
请参阅ip2long()和inet_pton()。
编辑:PHP_Compat包中有一个纯PHP的inet_pton实现。
我已经为你评论了这个功能。请注意,我对IPv6地址格式一无所知,所以我可以粗略地告诉你它做了什么但不是为什么。
<?php
/**
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
* @link http://php.net/inet_pton
* @author Arpad Ray <arpad@php.net>
*/
function php_compat_inet_pton($address) {
// Convert to IPv4 (numeric representation)
$r = ip2long($address);
// ip2long() will return FALSE if it's an invalid IPv4 address (or -1 if PHP earlier than 5.0.0)
if ($r !== false && $r != -1)
// if it didn't, then it *is* a valid IPv4 address
// We pack the number as unsigned long (always 32 bit, big endian byte order) and we're done
return pack('N', $r);
// Count the number of delimiters (:)
$delim_count = substr_count($address, ':');
// If none or more than 7, the address is not valid
if ($delim_count < 1 || $delim_count > 7) return false;
// Create an array with the delimited substrings
$r = explode(':', $address);
// Count the number of items
$rcount = count($r);
// If we have empty items, fetch the position of the first one
if (($doub = array_search('', $r, 1)) !== false) {
// We fill a $length variable with this rule:
// - If it's the first or last item ---> 2
// - Otherwhise ---> 1
$length = (!$doub || $doub == $rcount - 1 ? 2 : 1);
// Remove a portion of the array and replace it with something else
array_splice($r,
// We skip items before the empty one
$doub,
// We remove one or two items
$length,
// We replace each removed value with zeros
array_fill(0, 8 + $length - $rcount, 0)
);
}
// We convert each item from hexadecimal to decimal
$r = array_map('hexdec', $r);
// We add 'n*' at the beginning of the array (just a trick to use pack on all the items)
array_unshift($r, 'n*');
// We pack all the items as unsigned shorts (always 16 bit, big endian byte order)
$r = call_user_func_array('pack', $r);
// Return the resulting string
return $r;
}
答案 1 :(得分:1)
我将使用以下URL来编写我需要的功能:
http://www.zytrax.com/tech/protocols/ipv6.html
我将使用功能代码进行编辑。
编辑这就是:希望人们觉得这很有用。
class Connect {
/**
* Returns the IP in it's fullest format.
* @example
* ::1 => 0000:0000:0000:0000:0000:0000:0000:0001
* 220F::127.0.0.1 => 220F:0000:0000:0000:0000:0000:7F00:0001
* 2F:A1::1 => 002F:00A1:0000:0000:0000:0000:0000:0001
* @param string $ip Original/compressed/packed IPv6.
* @return string Full IP.
*/
protected static function fixIpv6($ip){
// fix double colon
if(strpos($ip,'::')!==false)$ip=str_replace('::',str_repeat(':',9-substr_count($ip,':')),$ip);
// fix each slot
$ip=explode(':',$ip);
foreach($ip as $k=>$v){
// fix empty/compressed slots
$ip[$k]=$v=str_pad($v,4,'0',STR_PAD_LEFT);
// fix ipv4-style slot
if(strpos($v,'.')!==false){
// initially empty buffer
$ip[$k]='';
// replace each number(byte) with a two-digit hex representation
foreach(explode('.',$v) as $v2){
$v=dechex(min((int)$v2,255));
if(strlen($v)==1)$v='0'.$v;
$ip[$k].=$v;
}
// add colon in between two pairs(bytes) (FFFFFFFF=>FFFF:FFFF)
$ip[$k]=implode(':',str_split($ip[$k],4));
}
}
return strtoupper(implode(':',$ip));
}
/**
* Compresses an IP to it's binary representation.
* @param string $ip A well-formatted full IPv4 or IPv6 address.
* @return string Binary representation of address.
*/
public static function compressIp($ip){
if(strpos($ip,':')!==false){ // ipv6
$ip=str_split(str_replace(':','',self::fixIpv6($ip)),2);
foreach($ip as $k=>$v)$ip[$k]=chr(hexdec($v));
return implode('',$ip);
}elseif(strpos($ip,'.')!==false){ // ipv4
$ip=explode('.',$ip);
if(count($ip)!=4)$ip=array(0,0,0,0);
return chr($ip[0]).chr($ip[1]).chr($ip[2]).chr($ip[3]);
}else throw new Exception('Unrecognized IP format: '.MB_SECURITY::snohtml($ip));
}
}