2024 年 PHP 日本大会

ip2long

(PHP 4, PHP 5, PHP 7, PHP 8)

ip2long将包含 (IPv4) Internet 协议点分地址的字符串转换为长整数

描述

ip2long(字符串 $ip): 整数|false

函数 ip2long() 从其 Internet 标准格式 (点分字符串) 表示生成 IPv4 Internet 网络地址的长整数表示。

ip2long() 也适用于不完整的 IP 地址。阅读 » http://ps-2.kev009.com/wisclibrary/aix52/usr/share/man/info/en_US/a_doc_lib/libs/commtrf2/inet_addr.htm 获取更多信息。

参数

ip

标准格式的地址。

返回值

返回长整数,如果 ip 无效则返回 false

示例

示例 #1 ip2long() 示例

<?php
$ip
= gethostbyname('www.example.com');
$out = "以下网址是等效的:<br />\n";
$out .= 'http://www.example.com/, http://' . $ip . '/, and http://' . sprintf("%u", ip2long($ip)) . "/<br />\n";
echo
$out;
?>

示例 #2 显示 IP 地址

第二个示例演示如何使用 printf() 函数打印转换后的地址

<?php
$ip
= gethostbyname('www.example.com');
$long = ip2long($ip);

if (
$long == -1 || $long === FALSE) {
echo
'无效的 IP,请重试';
} else {
echo
$ip . "\n"; // 192.0.34.166
echo $long . "\n"; // 3221234342 (在 32 位系统上由于整数溢出为 -1073732954)
printf("%u\n", ip2long($ip)); // 3221234342
}
?>

注释

注意:

因为 PHP 的 int 类型是有符号的,并且许多 IP 地址在 32 位架构上会导致负整数,因此需要使用 sprintf()printf() 的 "%u" 格式化程序来获取无符号 IP 地址的字符串表示。

注意:

由于整数溢出,在 32 位系统上,ip2long() 将为 IP 255.255.255.255 返回 -1

参见

  • long2ip() - 将长整数地址转换为 (IPv4) Internet 标准点分格式的字符串
  • sprintf() - 返回格式化的字符串

添加注释

用户贡献的注释 25 条注释

joe at joeceresini dot com
15 年前
将网络掩码 (例如:255.255.255.240) 转换为 CIDR 掩码 (例如:/28) 的快速方法

<?php
function mask2cidr($mask){
$long = ip2long($mask);
$base = ip2long('255.255.255.255');
return
32-log(($long ^ $base)+1,2);

/* 异或运算将给出反向掩码,
该掩码加 1 的以 2 为底的对数将返回
掩码中关闭的位数,并从
32 中减去该数得到 CIDR 表示法 */

}
?>
Mike B
7 年前
<?php
/*
给定一个 IP 地址和子网掩码,
通过使用按位运算符
确定子网地址、广播地址和通配符掩码

参考: https://php.net/manual/en/language.operators.bitwise.php
*/

$ip='10.10.10.7';
$mask='255.255.255.0';
$wcmask=long2ip( ~ip2long($mask) );
$subnet=long2ip( ip2long($ip) & ip2long($mask) );
$bcast=long2ip( ip2long($ip) | ip2long($wcmask) );
echo
"给定地址 $ip 和掩码 $mask, \n" .
"子网是 $subnet 并且广播是 $bcast \n" .
"通配符掩码为 $wcmask";

/*
给定地址 10.10.10.7 和掩码 255.255.255.0,
子网是 10.10.10.0 并且广播是 10.10.10.255
通配符掩码为 0.0.0.255
*/

?>
php dot net at kenman dot net
16 年前
致 Nate,他建议在 MySQL 数据库中使用 IP 的无符号版本没有理由

我认为这取决于您的应用程序,但我个人认为将 IP 存储为无符号数很有用,因为 MySQL 有两个原生函数 INET_ATON() 和 INET_NTOA(),它们的工作方式与 ip2long()/long2ip() 相同,_除了_它们生成无符号的对应物。因此,如果您愿意,您可以执行以下操作

-- IANA B 类保留/专用地址
SELECT * FROM `servers`
WHERE `ip` >= INET_ATON('192.168.0.0')
AND `ip` <= INET_ATON('192.168.255.255');

在我的当前应用程序中,我发现使用MySQL内置函数比使用PHP的对应函数更容易。

如果您好奇ATON和NTOA的含义:

ATON = 地址转数字,也即 ip2long
NTOA = 数字转地址,也即 long2ip
ir at ir id is at gm ai ld ot co m
17年前
请记住,将IP地址存储在数据库中作为整数(而不是十进制格式的15个字符的字符串,或十六进制格式的8个字符的字符串)要快数百倍。

以MySQL数据库在数千(或数百万!)行中搜索IP地址的典型案例为例;您要么对每个条目进行字符串比较,要么进行整数运算。如果您正确地创建索引,使用INT而不是VARCHAR进行查找速度将快100倍。

还要注意,整数在传递到数据库时不需要转义。 :)
david dot schueler at tel-billig dot de
15 年前
要从广播地址和网络掩码中获取网络地址,只需对其进行与运算即可

<?php
// 简单示例
$bcast = ip2long("192.168.178.255");
$smask = ip2long("255.255.255.0");
$nmask = $bcast & $smask;
echo
long2ip($nmask); // 将输出 192.168.178.0
?>

通过此示例,您可以检查给定的主机是否在您自己的本地网络中(在Linux上)。

<?php
/**
* 检查客户端IP是否在我们的服务器子网上
*
* @param string $client_ip
* @param string $server_ip
* @return boolean
*/
function clientInSameSubnet($client_ip=false,$server_ip=false) {
if (!
$client_ip)
$client_ip = $_SERVER['REMOTE_ADDR'];
if (!
$server_ip)
$server_ip = $_SERVER['SERVER_ADDR'];
// 从ifconfig中提取广播地址和网络掩码
if (!($p = popen("ifconfig","r"))) return false;
$out = "";
while(!
feof($p))
$out .= fread($p,1024);
fclose($p);
// 这是因为php.net的注释函数不允许长行。
$match = "/^.*".$server_ip;
$match .= ".*Bcast:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*";
$match .= "Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/im";
if (!
preg_match($match,$out,$regs))
return
false;
$bcast = ip2long($regs[1]);
$smask = ip2long($regs[2]);
$ipadr = ip2long($client_ip);
$nmask = $bcast & $smask;
return ((
$ipadr & $smask) == ($nmask & $smask));
}
?>
spinyn at gmail dot com
15 年前
只想对kaputt对有效匹配主机到IP范围任务的宝贵贡献添加一条评论。如果IP的二进制表示不包含前导零,则脚本运行良好。不幸的是,decbin() 的工作方式似乎是,第一个IP四字节的二进制表示中的前导零会被丢弃。如果您试图匹配清单中的所有可能候选者,这是一个严重的问题。在这些情况下,需要添加回前导零才能获得0-127(或二进制等效值0-01111111)之间值的准确匹配。

我提出的解决此问题的方案是以下函数

<?php
function addLeadingZero($ip) {
if ((
$result = (32 - strlen($ip))) > 0)
return
str_repeat("0", $result).$ip;
}
?>
one tiger one at gee mail dot comm
17年前
我编写了一个小型函数来验证网络掩码(我们有一个表单,其中输入给定服务器的网络掩码,我想确保它是有效的)。希望这对您有用。

<?php
// 网络掩码验证器 //
function checkNetmask($ip) {
if (!
ip2long($ip)) {
return
false;
} elseif(
strlen(decbin(ip2long($ip))) != 32 && ip2long($ip) != 0) {
return
false;
} elseif(
ereg('01',decbin(ip2long($ip))) || !ereg('0',decbin(ip2long($ip)))) {
return
false;
} else {
return
true;
}
}
?>
Karl Rixon
10年前
手册中指出“ip2long() 也适用于不完整的IP地址”,但这依赖于系统,因此不可靠。例如,在我的系统上,ip2long() 将对不完整的地址返回 FALSE。

<?php
var_dump
(ip2long("255.255")); // bool(false)
?>

这是因为如果可用,ip2long 将使用 inet_pton,它不支持不完整的地址。如果您的系统上 inet_pton 不可用,则将使用 inet_addr,并且不完整的地址将按说明工作。
jpmarcotte at gmail dot com
16 年前
在使用下面jbothe的代码和一些“$mask = 0xFFFFFFFF << (32 - $bits)”类型的代码的组合时,我在64位机器上的一些后续计算中遇到了错误。

请记住,当您分析旨在被视为32位宽的数字(例如IP地址)时,您可能需要截断它们。在不依赖其他库的情况下,只需使用“ & 0xFFFFFFFF”就可以轻松地跟踪在64位机器上可能以不同结果结束的任何计算。

尽管在许多情况下,使用“~0 << ...”进行初始移位以创建网络掩码似乎比“0xFFFFFFFF << ...”更简单。但是,我不知道它是否能保证后续操作按预期工作。
Aleksey Kuznetsov
12年前
不幸的是,sprintf('%u', ...) 效率低下,它返回整数的字符串表示而不是整数。
这是一个我用来将IP转换为与MySQL兼容的有符号整数的函数

function ip2int($ip) {
if (!$r = ip2long($ip)) return 0; // 即使IP无效,我们也希望返回0而不是false
if ($r > 2147483647)
$r-= 4294967296;
return $r; // ok
}
replay111 at tlen dot pl
12年前
您好,
基于上面的例子,我已经将IPFilter类与netMatch函数混合,这给了我一个完整的用于IPv4检查的类,包括CIDR IP格式。

<?php
class IP4Filter {

private static
$_IP_TYPE_SINGLE = 'single';
private static
$_IP_TYPE_WILDCARD = 'wildcard';
private static
$_IP_TYPE_MASK = 'mask';
private static
$_IP_TYPE_CIDR = 'CIDR';
private static
$_IP_TYPE_SECTION = 'section';
private
$_allowed_ips = array();

public function
__construct($allowed_ips) {
$this->_allowed_ips = $allowed_ips;
}

public function
check($ip, $allowed_ips = null) {
$allowed_ips = $allowed_ips ? $allowed_ips : $this->_allowed_ips;

foreach (
$allowed_ips as $allowed_ip) {
$type = $this->_judge_ip_type($allowed_ip);
$sub_rst = call_user_func(array($this, '_sub_checker_' . $type), $allowed_ip, $ip);

if (
$sub_rst) {
return
true;
}
}

return
false;
}

private function
_judge_ip_type($ip) {
if (
strpos($ip, '*')) {
return
self :: $_IP_TYPE_WILDCARD;
}

if (
strpos($ip, '/')) {
$tmp = explode('/', $ip);
if (
strpos($tmp[1], '.')) {
return
self :: $_IP_TYPE_MASK;
} else {
return
self :: $_IP_TYPE_CIDR;
}
}

if (
strpos($ip, '-')) {
return
self :: $_IP_TYPE_SECTION;
}

if (
ip2long($ip)) {
return
self :: $_IP_TYPE_SINGLE;
}

return
false;
}

private function
_sub_checker_single($allowed_ip, $ip) {
return (
ip2long($allowed_ip) == ip2long($ip));
}

private function
_sub_checker_wildcard($allowed_ip, $ip) {
$allowed_ip_arr = explode('.', $allowed_ip);
$ip_arr = explode('.', $ip);
for (
$i = 0; $i < count($allowed_ip_arr); $i++) {
if (
$allowed_ip_arr[$i] == '*') {
return
true;
} else {
if (
false == ($allowed_ip_arr[$i] == $ip_arr[$i])) {
return
false;
}
}
}
}

private function
_sub_checker_mask($allowed_ip, $ip) {
list(
$allowed_ip_ip, $allowed_ip_mask) = explode('/', $allowed_ip);
$begin = (ip2long($allowed_ip_ip) & ip2long($allowed_ip_mask)) + 1;
$end = (ip2long($allowed_ip_ip) | (~ ip2long($allowed_ip_mask))) + 1;
$ip = ip2long($ip);
return (
$ip >= $begin && $ip <= $end);
}

private function
_sub_checker_section($allowed_ip, $ip) {
list(
$begin, $end) = explode('-', $allowed_ip);
$begin = ip2long($begin);
$end = ip2long($end);
$ip = ip2long($ip);
return (
$ip >= $begin && $ip <= $end);
}

private function
_sub_checker_CIDR($CIDR, $IP) {
list (
$net, $mask) = explode('/', $CIDR);
return (
ip2long($IP) & ~((1 << (32 - $mask)) - 1) ) == ip2long($net);
}

}
?>

这段代码对我来说运行良好,所以我要感谢你们所有人!!!
schat
5年前
抱歉,我刚才写错了,对不起。这是正确的版本。谢谢。

<?php
/**
* 将CIDR转换为IP范围
* 来自: <https://github.com/www-schat-top>
* @param string $cidr "192.168.0.0/23"
* @return array ["192.168.0.0", "192.168.1.255"]
*/
function cidr2range($cidr){
list(
$subnet, $mask ) = explode( '/', $cidr );
return [
$subnet, long2ip(ip2long( $subnet ) | (pow(2,( 32 - $mask ))-1))];
}
?>
jwadhams1 at yahoo dot com
15 年前
我想在 kaputt 和 spinyn 的贡献基础上进行改进,我认为这种方法更直观一些(例如,让 sprintf 完成所有二进制转换和填充,让 substr_compare 完成修剪和比较)。

<?php
function ip_in_network($ip, $net_addr, $net_mask){
if(
$net_mask <= 0){ return false; }
$ip_binary_string = sprintf("%032b",ip2long($ip));
$net_binary_string = sprintf("%032b",ip2long($net_addr));
return (
substr_compare($ip_binary_string,$net_binary_string,0,$net_mask) === 0);
}

ip_in_network("192.168.2.1","192.168.2.0",24); //true
ip_in_network("192.168.6.93","192.168.0.0",16); //true
ip_in_network("1.6.6.6","128.168.2.0",1); //false
?>
rasmus at mindplay dot dk
11 年前
正如其他人所指出的,此函数的返回值在 32 位和 64 位平台上不一致。

为了在 32/64 位平台(以及 Windows)上获得一致的行为,最好的方法是使用最低公分母:强制将 ip2long() 的返回值转换为带符号的 32 位整数,例如:

var_dump(unpack('l', pack('l', ip2long('255.255.255.0'))));

这看起来很愚蠢,但它可以在所有平台上提供一致的带符号整数值。

(pack() 和 unpack() 的参数都是小写字母“L”,而不是数字“1”,如果在您的屏幕上看起来像那样的话……)
oo dot para at gmail dot com
10年前
如果您想使用此函数验证 IP 地址,请务必小心
应该改用 filter_var 函数来验证 IP 地址。

<?php
$ip
= '192.168.0355.24';
var_dump(ip2long($ip) !== false); // true (预期为 false)
var_dump(filter_var($ip, FILTER_VALIDATE_IP) !== false); // false

$ip = '192.168.355.24';
var_dump(ip2long($ip) !== false); // false
var_dump(filter_var($ip, FILTER_VALIDATE_IP) !== false); // false
?>
PandoraBox2007 at gmail dot com
13 年前
通用 IPv4/IPv6

<?php
// 编码 --
function encode_ip ($ip)
{
$d = explode('.', $ip);
if (
count($d) == 4) return sprintf('%02x%02x%02x%02x', $d[0], $d[1], $d[2], $d[3]);

$d = explode(':', preg_replace('/(^:)|(:$)/', '', $ip));
$res = '';
foreach (
$d as $x)
$res .= sprintf('%0'. ($x == '' ? (9 - count($d)) * 4 : 4) .'s', $x);
return
$res;
}

// 解码
function decode_ip($int_ip)
{
function
hexhex($value) { return dechex(hexdec($value)); };

if (
strlen($int_ip) == 32) {
$int_ip = substr(chunk_split($int_ip, 4, ':'), 0, 39);
$int_ip = ':'. implode(':', array_map("hexhex", explode(':',$int_ip))) .':';
preg_match_all("/(:0)+/", $int_ip, $zeros);
if (
count($zeros[0]) > 0) {
$match = '';
foreach(
$zeros[0] as $zero)
if (
strlen($zero) > strlen($match))
$match = $zero;
$int_ip = preg_replace('/'. $match .'/', ':', $int_ip, 1);
}
return
preg_replace('/(^:([^:]))|(([^:]):$)/', '$2$4', $int_ip);
}
$hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
return
hexdec($hexipbang[0]). '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
}
?>

数据库
`user_ip` varchar(32) DEFAULT NULL
f dot wiessner at smart-weblications dot net
15 年前
这里有一些可用的 ip2long6 和 long2ip6 函数 - 请记住,这需要 php gmp 库

<?php

$ipv6
= "2001:4860:a005::68";

function
ip2long6($ipv6) {
$ip_n = inet_pton($ipv6);
$bits = 15; // 16 x 8 bit = 128bit
while ($bits >= 0) {
$bin = sprintf("%08b",(ord($ip_n[$bits])));
$ipv6long = $bin.$ipv6long;
$bits--;
}
return
gmp_strval(gmp_init($ipv6long,2),10);
}

function
long2ip6($ipv6long) {

$bin = gmp_strval(gmp_init($ipv6long,10),2);
if (
strlen($bin) < 128) {
$pad = 128 - strlen($bin);
for (
$i = 1; $i <= $pad; $i++) {
$bin = "0".$bin;
}
}
$bits = 0;
while (
$bits <= 7) {
$bin_part = substr($bin,($bits*16),16);
$ipv6 .= dechex(bindec($bin_part)).":";
$bits++;
}
// 压缩

return inet_ntop(inet_pton(substr($ipv6,0,-1)));
}

print
$ipv6long = ip2long6($ipv6)."\n";
print
$ipv6 = long2ip6($ipv6long)."\n";

?>

输出

42541956150894553250710573749450571880
2001:4860:a005::68
Ian B
17年前
注意:不应将 ip2long() 用于 CIDR 计算。
相反,您应该使用以下类似的方法:

<?php
/* 从数据库中的 ban 获取基数和位数 */
list($base, $bits) = explode('/', $CIDR);

/* 现在将其拆分为其类别 */
list($a, $b, $c, $d) = explode('.', $base);

/* 现在进行一些位移/切换操作以转换为整数 */
$i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
$mask = $bits == 0 ? 0 : (~0 << (32 - $bits));

/* 这是我们的最小整数 */
$low = $i & $mask;

/* 这是我们的最大整数 */
$high = $i | (~$mask & 0xFFFFFFFF);

/* 现在将我们正在检查的 IP 拆分为类别 */
list($a, $b, $c, $d) = explode('.', $iptocheck);

/* 现在将我们正在检查的 IP 转换为整数 */
$check = ($a << 24) + ($b << 16) + ($c << 8) + $d;

/* 如果 IP 在范围内,包括最高/最低值,则它在 CIDR 范围内 */
if ($check >= $low && $check <= $high)
return
1;
else
return
0;
?>

这意味着您应该每次都检查 IP
地址是否具有正确的格式。
pink at pink dot art dot pl
12年前
请注意,在运行 64 位系统时,ip2long 将产生一个 64 位整数,该整数不适合 MySQL INT,您可以使用 BIGINT 或 INT UNSIGNED,因为在 64 位系统上,ip2long 永远不会返回负整数。另请参见 https://bugs.php.net/bug.php?id=54338
匿名
20 年前
我作为面向对象编程的小练习,重写了 jbothe at hotmail dot com 的函数,并添加了几个额外的函数。

<?php

//--------------
// IPv4 类
class ipv4
{
var
$address;
var
$netbits;

//--------------
// 创建新类
function ipv4($address,$netbits)
{
$this->address = $address;
$this->netbits = $netbits;
}

//--------------
// 返回IP地址
function address() { return ($this->address); }

//--------------
// 返回网络位数
function netbits() { return ($this->netbits); }

//--------------
// 返回子网掩码
function netmask()
{
return (
long2ip(ip2long("255.255.255.255")
<< (
32-$this->netbits)));
}

//--------------
// 返回地址所在的网络
function network()
{
return (
long2ip((ip2long($this->address))
& (
ip2long($this->netmask()))));
}

//--------------
// 返回地址所在的广播地址
function broadcast()
{
return (
long2ip(ip2long($this->network())
| (~(
ip2long($this->netmask())))));
}

//--------------
// 返回子网掩码的反掩码
function inverse()
{
return (
long2ip(~(ip2long("255.255.255.255")
<< (
32-$this->netbits))));
}

}

$ip = new ipv4("192.168.2.1",24);
print
"地址: $ip->address()\n";
print
"网络位数: $ip->netbits()\n";
print
"子网掩码: $ip->netmask()\n";
print
"反掩码: $ip->inverse()\n";
print
"网络: $ip->network()\n";
print
"广播地址: $ip->broadcast()\n";
?>
admin at wudimei dot com
12年前
<?php

/**
*
*从CIDR(网络ID和掩码长度)获取第一个IP和最后一个IP
* 我会将这个函数集成到“Rong Framework”中 :)
* @author [email protected]
* @param string $cidr 56.15.0.6/16 , [网络ID]/[掩码长度]
* @return array $ipArray = array( 0 =>"网络的第一个IP", 1=>"网络的最后一个IP" );
* $ipArray的每个元素类型都是长整型,使用long2ip( $ipArray[0] )将其转换为IP字符串。
* 例如:
* list( $long_startIp , $long_endIp) = getIpRange( "56.15.0.6/16" );
* echo "起始IP:" . long2ip( $long_startIp );
* echo "<br />";
* echo "结束IP:" . long2ip( $long_endIp );
*/

function getIpRang( $cidr) {

list(
$ip, $mask) = explode('/', $cidr);

$maskBinStr =str_repeat("1", $mask ) . str_repeat("0", 32-$mask ); //子网掩码二进制字符串
$inverseMaskBinStr = str_repeat("0", $mask ) . str_repeat("1", 32-$mask ); //反掩码

$ipLong = ip2long( $ip );
$ipMaskLong = bindec( $maskBinStr );
$inverseIpMaskLong = bindec( $inverseMaskBinStr );
$netWork = $ipLong & $ipMaskLong;

$start = $netWork+1;//去掉网络号 ,忽略网络ID(例如:192.168.1.0)

$end = ($netWork | $inverseIpMaskLong) -1 ; //去掉广播地址,忽略广播IP(例如:192.168.1.255)
return array( $start, $end );
}
?>
alex at alex-at dot ru
8年前
以下是我编写的将前缀转换为掩码和将掩码转换为前缀的函数版本。如果您不需要完整性预检查,可以移除每个函数的第一行(if/preg)。

function prefix2Mask($prefix)
{
if (!preg_match('#^(?:0*[0-2]?[0-9]|3[0-2])$#', $prefix)) return false; # 前缀错误
return long2ip(0xffffffff << (32 - $prefix));
}

function mask2Prefix($mask)
{
if (!preg_match('#^(?:(?:[0-1][0-9][0-9]|2[0-4][0-9]|25[0-5]|[0-9][0-9]|[0-9])\.){3}'.
'(?:[0-1][0-9][0-9]|2[0-4][0-9]|25[0-5]|[0-9][0-9]|[0-9])$#', $mask))
return false; # 掩码错误
$m2p = str_pad(substr(decbin(ip2long($mask)), -32, 32), 32, '0', STR_PAD_LEFT);
if (!preg_match('#^(1*)0*$#', $m2p, $m)) return false; # 掩码错误
return strlen($m[1]);
}
laacz at php dot net
17年前
只是为了节省您的时间。

注意,IP地址中的八位字节被视为数字。因此,“10.0.0.11”不等于“10.0.0.011”。“011”是八进制数(8进制),因此它转换为“9”。您甚至可以更进一步,看到“10.0.0.0xa”也适用(等于“10.0.0.16”)。

但这并非PHP问题。
chrisp-phpnet at inventivedingo dot com
16 年前
我在我的lighttpd web服务器上使用REMOTE_ADDR调用此函数时遇到问题。事实证明,此服务器上安装了IPv6,因此即使REMOTE_ADDR是IPv4地址,它也使用IPv6的IPv4兼容模式进行格式化。例如,10.0.0.1 变成 ::ffff:10.0.0.1,这导致iplong 报告地址无效,而不是正确解析它。

正确的解决方法当然是更新我的基础设施,使其与IPv6完全兼容;但在我的特定情况下,这将涉及大量的重新设计。因此,在此期间,我使用了这个快速简便的解决方法。

<?php
$ip
= htmlspecialchars($_SERVER['REMOTE_ADDR']);
if (
strpos($ip, '::') === 0) {
$ip = substr($ip, strrpos($ip, ':')+1);
}
$host = ip2long($ip);
?>

不好看,但有效。
ken at expitrans dot com
19年前
以下是所有各种注释的合并形式,以及更好的(正确的)网络匹配函数。

<?php

function net_match($network, $ip) {
// 判断形如 192.168.17.1/16 或
// 127.0.0.1/255.255.255.255 或 10.0.0.1 的网络是否匹配给定的 IP
$ip_arr = explode('/', $network);
$network_long = ip2long($ip_arr[0]);

$x = ip2long($ip_arr[1]);
$mask = long2ip($x) == $ip_arr[1] ? $x : 0xffffffff << (32 - $ip_arr[1]);
$ip_long = ip2long($ip);

// echo ">".$ip_arr[1]."> ".decbin($mask)."\n";
return ($ip_long & $mask) == ($network_long & $mask);
}

echo
net_match('192.168.17.1/16', '192.168.15.1')."\n"; // 返回 true
echo net_match('127.0.0.1/255.255.255.255', '127.0.0.2')."\n"; // 返回 false
echo net_match('10.0.0.1', '10.0.0.1')."\n"; // 返回 true

?>
To Top