IP 地址 32 位,按每8位一段分成4段,你想转换的掩码如:
CIDR : 8
十进制: 255 . 0 . 0 . 0
二进制:11111111 . 00000000 . 00000000 . 00000000
其实这里 CIDR 指的就是IP地址中作为网络号的bit的位数(如上从左至右前8位为1),所以想要将 CIDR 转换为子网掩码,只需要根据 CIDR 从左至右将对应比特位设为1,其他位为0,然后转换为4段十进制表示就行了。
vec 函数就是用来对指定位进行操作的,它有三个参数,形式如下:
vec($var, $offset, $unit_len)
$var 代表要操作的位串;
$offset 代表偏移量;
$unit_len 就是 perldoc -f vec 里所说的 BITS,它指的是 vec 操作的单位元素大小(多少个位),所以我这里用 $unit_len 来表式更直白一点。
在你的例子中,只需要初始化一个 32 位长度,每位都是0的串,即:
vec( $mask, 0, 32 ) = 0x0;
然后根据 CIDR 的值,将对应位设为1,即:
foreach (1..$length){ # 这里 $lenght 就是 CIDR 的值
vec( $mask, (32-$_), 1 ) = 0x01; # 从右往左,将8位设为1
}
这里为啥用 "(32-$_)"(即从后往前操作)?这是因为当前情况下,操作的位串是 little-endian 的(见 vec 文档),即:
二进制:11111111 . 00000000 . 00000000 . 00000000
按 little-endian 方式就成了 (即从右往左):
二进制:00000000 . 00000000 . 00000000 . 11111111
所以我们 用 vec 操作 $mask 的时候, offset 是从右往左递减1的。
操作完后,sprintf( "%vd", $mask ) 将 $mask 按十进制打印出来,其中 "%vd" 告诉 perl, $mask 是个 vec 整数串。
操作完后,用 split + reverse 将它再倒过来,就是我们所求的对应掩码了。
2011/5/23 perl01 <perl01@live.cn>
--问个问题,vec函数是如何将1 ~ 32 转换成掩码的,比如24对应255.255.255.0.foreach (1..32){printf "$_ => %s\n", &cidr2mask($_);}exit 1;sub cidr2mask{my $length = shift;my $mask = '';vec( $mask, 0, 32 ) = 0x0; # 这里开始我就不是太懂了,vec函数的原理是什么?foreach (1..$length){vec( $mask, (32-$_), 1 ) = 0x01; #这里呢?}$mask = join( '.', reverse( split( /\./, sprintf( "%vd", $mask ) ) ) );return $mask;}2011-05-23
perl01
您收到此邮件是因为您订阅了 Google 网上论坛的“PerlChina Mongers 讨论组”论坛。
要向此网上论坛发帖,请发送电子邮件至 perlchina@googlegroups.com。
要取消订阅此网上论坛,请发送电子邮件至 perlchina+unsubscribe@googlegroups.com。
若有更多问题,请通过 http://groups.google.com/group/perlchina?hl=zh-CN 访问此网上论坛。
--
您收到此邮件是因为您订阅了 Google 网上论坛的"PerlChina Mongers 讨论组"论坛。
要向此网上论坛发帖,请发送电子邮件至 perlchina@googlegroups.com。
要取消订阅此网上论坛,请发送电子邮件至 perlchina+unsubscribe@googlegroups.com。
若有更多问题,请通过 http://groups.google.com/group/perlchina?hl=zh-CN 访问此网上论坛。
没有评论:
发表评论