加了一些注释,主要是为了复习一些包的使用。还有多线程的一些使用方法。
#!/usr/bin/perl use Getopt::Long; #这个包使用来做选项用的 use threads; #这个是线程包 use Thread::Semaphore; #这个是线程信号量控制使用的包 use Smart::Comments; #这个会在用FOREACH 的时候弄出进度条..不过没成功使用... use Net::Ping; #这个是主角,也是ping的使用包 use threads::shared; #用于线程当中共享变量 use Socket; #用于端口扫描 #设定接受选项 -thread设置线程数量 #-Ip 设置要检查的Ip段 GetOptions("thread=i" => \$thread_max, "Ip=s" =>\$ip_check, "Out=s" =>\$output); #创建信号,用于控制线程 my $se = Thread::Semaphore->new($thread_max); my $se2=Thread::Semaphore->new( 10 ); $p=Net::Ping->new(); #地一个是共享出来的变量,用来统计存活的IP, #第二个用来统计端口开放数量用的。 share(@alive_ip); share($sum_port); #调用子程序去生成Ip组, #所存放的IP即是需要进行检测的IP. @bok=&IpMap_main($ip_check); #** #** @ main 方法的开始 #** foreach (@bok){ # print ${$se}; # 这里的${$se}是查看信号里面的数量 # 如果到达了0,即开始检查线程中的任务是否执行完毕 # 如果执行完毕,则Join掉进程 if(${$se} <= 0 ){ #这个大概意思是检查线程列表里面可以JOIN的线程 for my $t(threads->list(threads::joinable)){ # 因为我们不关心返回值,所以直接剥离线程 # 如果你关心返回的值,则使用JOIN $t->join(); # 信号量加1 $se->up(); } redo; } #先申请后使用,这个是CU论坛里看到的, #必须先申请后使用,才符合规范。 $se->down(); # 创建线程并处理Foreach出来的数据 threads->create(\&IpMap_ping,$_); } #对剩余线程进行剥离, #不管结果如何,总会有剩下的线程。 for my $t(threads->list()){ # $t->detach(); $t->join(); } $ok_list=@alive_ip; #获取存活IP的数量,同时可以进行下一步处理。 print "存活的IP数量:$ok_list\n"; #print "列表保存位置:$output\n"; # 对存活的iP进行端口扫描 foreach $keys (@alive_ip){ if(${$se} <= 0 ){ for my $t(threads->list(threads::joinable)){ $t->join(); $se2->up(); } redo; } $se2->down(); threads->create(\&IpScan_main,$keys); } for my $t(threads->list()){ $t->join(); } print "一共开放端口数量为:$sum_port\n"; sub IpScan_main { local($wscan_ip)=shift; for($port=0;$port<=65535;$port++){ $ip_a= sockaddr_in($port, inet_aton($wscan_ip)); # 对IP进行端口扫描探测 $proto=getprotobyname('tcp'); # 选择扫描方式 socket(SOCK, PF_INET, SOCK_STREAM,$proto); if(connect(SOCK,$ip_a)){ # 如果端口存活 print "[#] host:$wscan_ip:$port is Open! [#]\n"; $sum_port++; # 统计开放端口数量 }else{ close(SOCK); } } } sub IpMap_main { local($ip)=shift; @list=split(/\./,$ip); if(@list==3){ @ip_group=map{"$ip.$_"}(1..254); return @ip_group; }elsif(@list==2){ #我个人觉得这种方案比较好。严谨一些。与下面的For相同。 @ip_list=map{"$ip.$_"}(0..254); for my $key (@ip_list){ push @ip_group,map{"$key.$_"}(1..254); } return @ip_group; #这里有两种方案,For循环的方案也可以。 # for($i=0;$i<=254;$i++){ # for($k=1;$k<=254;$k++){ # push @ip_group,"$ip.$i.$k\n"; # } # } # return @ip_group; }else{ print "输入区有错误!\n"; exit(1); } } sub IpMap_ping { local($host_ip)=shift; if($p->ping($host_ip)){ print "[*]$host_ip ---OK![*]\n"; push @alive_ip,$host_ip; } $p->close(); }