一个变量而不是多个

时间:2017-08-26 07:43:40

标签: php mysql mikrotik

关于我的其他问题Transfer IP accounting to single row table 我使用ip2long和long2ip来回转换...有没有办法可以指定这样的范围:$ iprange =" 192.168.0.1-192.168.255.254&#34 ;;而不是$ iprangestart =" 192.168.0.1&#34 ;; $ iprangeend =" 192.168.255.254&#34 ;;并且还能够在一个变量中指定由逗号分隔的多个范围,如$ ipranges =" 192.168.0.1-192.168.255.254,10.0.0.1-10.255.255.254&#34 ;;

或者即使可能,也可以使用CIDR表示法指定范围,例如:     $ iprange =" 192.168.0.0 / 16,10.0.0.0/8" ;;

IP到long和long到IP代码:     

include ("config.php");
$conn = mysqli_connect($SQLserver, $SQLusername, $SQLpassword, $SQLdatabase);
if (!$conn) {
    die("Could not connect: " . mysqli_connect_error());
}
$IP = "192.168.0.1";
$IPEND = "192.168.255.254";

$NOTIP = "192.168.0.1";
$NOTIPEND = "192.168.255.254";




$IP = ip2long($IP);
$IPEND = ip2long($IPEND);
$NOTIP = ip2long($NOTIP);
$NOTIPEND = ip2long($NOTIPEND);
$query = "SELECT * , SUM(bytes) AS total_bytes FROM ipaccountingtest WHERE src_address BETWEEN $IP AND $IPEND AND NOT dst_address BETWEEN $NOTIP AND $NOTIPEND GROUP BY src_address";



$result = mysqli_query($conn,$query);


echo "<table>";
echo "<tr><th>src_address</th><th>Bytes</th></tr>";

while($row = mysqli_fetch_array($result)) {
if (isset($row['src_address'])) {
    $src_address = $row['src_address'];
    $src_address = long2ip($src_address);
}
/*if (isset($row['dst_address'])) {
    $dst_address = $row['dst_address'];
} */
if (isset($row['total_bytes'])) {
    $bytes = $row['total_bytes'];
} 

echo "<tr><td>".$src_address."</td><td>".$bytes."</td></tr>";
} 

echo "</table>";
mysqli_close($conn);
?>

此外,我没有在文档中使用IP范围,而是希望将其插入到sql中,我在数据库中添加了一个表,如下所示

Table name: accountingipranges

column1 id

column2 iprangestart

column3 iprangeend

如何让我的脚本从数据库中取出然后以与之前相同的方式显示它,而不是在脚本中使用IP范围并让它查询数据库?

如何输出表格如下:

IP地址|下载|上传| TOTAL

一个例子:

IP ADDRESS | DOWNLOAD | UPLOAD | TOTAL
192.168.2.3  1024       1024     2046

我需要脚本来排除自己的子网记帐,例如,它不能计算往返于excludeaccountingipranges表中指定范围的流量

excludeaccountingipranges表也类似于accountingipranges表 例如:

Table name: excludeaccountingipranges

column1 id

column2 iprangestart

column3 iprangeend

2 个答案:

答案 0 :(得分:0)

我会把你的范围放到一个数组中。这样,您可以指定任何范围和您喜欢的范围。像这样:

$ranges = array(
    array(
        'start' => '192.168.0.1',
        'end'   => '192.168.255.254'
    ),
    array(
        'start' => '10.0.0.1',
        'end'   => '10.255.255.254'
    )
)

然后使用foreach()循环遍历它们并构造SQL查询:

$wheres = array();

foreach ( $ranges as $range ) {
    $where[] = '( src_address BETWEEN ' . ip2long( $range['start'] ) . ' AND ' . ip2long( $range['end'] ) . ' )';
}

然后完成你的查询:

$query = "
SELECT *, SUM( bytes ) AS total_bytes
  FROM ipaccountingtest
 WHERE ( " . implode( ' OR ', $wheres ) . " )
 GROUP BY src_address";

所以这就是这一切:

  • 将所有IP范围放入数组中。
  • 遍历数组以构建WHERE子句。
  • 创建查询,将WHERE子句放在适当位置,将每个IP范围与OR分开,以便返回与指定的所有IP范围关联的数据。

使用上述IP范围和循环,这里是最终查询的样子:

SELECT *, SUM( bytes ) AS total_bytes
  FROM ipaccountingtest
 WHERE (( src_address BETWEEN 3232235521 AND 3232301054 ) OR ( src_address BETWEEN 167772161 AND 184549374 ))
 GROUP BY src_address

请注意,我还没有对上述任何代码进行过测试..可能存在语法错误或类似内容。然而,这里的想法是传达你可以实现你想要的东西的方法。如果您最终在这里发现错误,您可以提供有关它们的详细信息,并且我会看到我可以做些什么来帮助解决它们。但该方法应该是合理的,任何错误都应该很容易解决。

答案 1 :(得分:0)

我已经想出了要为自己想做的功能

function cidrToRange($ranges) {
    if(!empty($ranges)) {
        $ranges = str_replace(" ", "", $ranges);
        $ranges_array = explode(',', $ranges);


            foreach($ranges_array as $ip_and_cidr) {
                $cidr = explode('/', $ip_and_cidr);
                $range['start'] = long2ip((ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1]))));
                $range['end'] = long2ip((ip2long($range['start'])) + pow(2, (32 - (int)$cidr[1])) - 1);
                if(!isset($ip_ranges)) {
                    $ip_ranges = array($range);
                } else {
                    $ip_ranges = array_merge($ip_ranges, array($range));
                }
                //print_r($ip_ranges);
            }
        return($ip_ranges);
    } else {
        return(false);
    }
}