Skip to content

Instantly share code, notes, and snippets.

@azhai
Last active June 14, 2016 12:09
Show Gist options
  • Save azhai/5955286 to your computer and use it in GitHub Desktop.
Save azhai/5955286 to your computer and use it in GitHub Desktop.
PHP判断是否中国大陆IP
<?php
/*
需要存放IP段起止地址的二进制文件cnips.dat
*/
/**
* 二分(折半)查找算法
*/
function binary_search($total, $callback)
{
$args = func_get_args();
array_shift($args);
$step = $total;
$offset = 0;
$sign = 1;
do {
$step = ceil($step / 2);
$offset += $sign * $step;
$args[0] = $offset;
$sign = call_user_func_array($callback, $args);
} while ($sign !== 0 && $step > 1);
return $sign === 0;
}
function compare_ip($offset, $ip, $fp)
{
fseek($fp, ($offset - 1) * 8);
$start_ip = fread($fp, 4); //读取之后0-4个字节
$end_ip = fread($fp, 4); //读取之后4-8个字节
$sign = strcmp($ip, bin2hex($start_ip));
if ($sign >= 0 && strcmp($ip, bin2hex($end_ip)) <= 0) {
return 0; //在IP段范围内(含两端)
}
else { //指出下次偏移的方向
return $sign;
}
}
/**
* 是否中国大陆IP
*/
function ip_in_china($ip_address)
{
//IP段数据文件,每个IP表示成一个8位hex整数,不足8位的前面补0
$datfile = 'cnips.dat';
$total = floor(filesize($datfile) / 8); //IP段总数
//将要判断的IP转为8位hex整数
$ip = sprintf('%08x', ip2long($ip_address));
$fp = fopen($datfile, 'rb');
//比较IP并决定方向
$result = binary_search($total, 'compare_ip', $ip, $fp); //请在这以后关闭文件
fclose($fp);
return $result;
}
@cloudsnet
Copy link

IP段起止地址的二进制文件cnips.dat 在哪里可以下载到呢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment