пишу сканер для локальной сети. он разыскивает активные FTP-серверы в определенном диапазоне адресов. проблема в том что работает слишком медленно - прога однопоточная и проблемы с таймаутом сокета. нужен пример (код) простейшего быстрого сканера. заранее благодарен
написание подобной штуки на перле - это обязательно? Если нет, то можно воспользоваться тем же nmap (пример сканит ftp для адресов с 192.168.250.1 по 192.168.250.20):sudo nmap -sS -p 21 192.168.250.1-20 | less
Если написать сканер именно на перле - дело чести :), то прямо сейчас помочь не могу. Если не забуду, попозже гляну в своей помойке. Лепил как-то нечто подобное в качестве "домашнего задания", только давно это было. И качество кода там скорее всего хорошо соответствует слову "лепил"... :)
http://search.cpan.org/~maxschube/Nmap-Scanner-0.9/lib/Nmap/...
пишу поисковик для локалки. более года юзается nmap и но этот вариант мне не нравится :]
хочу всё реализовать на perl (как уже говорилось "дело чести") - считаю что это сделает систему проще.
что-то типа этого подойдет или я неправильно понял задачу?--------------------------------
#!/usr/bin/perl
use strict;
use warnings;
use Net::Ping;sub who_send_ack(@);
sub main;main;
sub main {
my @acked;
# дурацкая передача параметров, переделывать лениво
@acked = who_send_ack( 192, 168, 251, 1..100 );
print "$_\n" foreach @acked;
}sub who_send_ack(@) {
my( $first_three_octets, @last_octets, @hosts, $p, @acked );$first_three_octets .= shift() . "." for 1..3;
push @hosts, map { $first_three_octets . $_ } @_;$p = Net::Ping->new( "syn", 2 );
$p->{port_num} = getservbyname( "ftp", "tcp" );
foreach my $host ( @hosts ) {
$p->ping( $host );
}
while( my( $host,$rtt,$ip ) = $p->ack ) {
push @acked, $ip;
}
return @acked;
}
--------------------------------
>Отправлено andy, 08-Май-07 09:18
>что-то типа этого подойдет или я неправильно понял задачу?
>
после того что нарисовал andy даже как то неудобно отправлять свою поделку,
по хорошему нужно твою процедуру соединений запихнуть в тред, и создать несколько тредов, но поскольку у меня перл собран без тредов, я реализовал пример в котором создается несколько процессов, они работают каждый со своей задачей(для тебя это диапазон адресов) и возвращают через пайп результаты главному процессу. Вообщем основная проблема в том что для того чтобы определить что чтото работает по сети, это то что приходиться долго ждать ответа, предлагаю решить ее тем что ждать будет не один главный процесс, а несколько подчиненных.Я написал не сетевой приложение но его легко можно под него переделать, сильная вещь получилась, особенно когда задаешь 1500 тыщи процессов. работает но у меня памяти не хватает ;-)))
вот смотри:
-----------------------------------------------------------
#!/usr/bin/perl -w
# file: fork10and_pipe_exchange.pluse IO::File;
use POSIX 'WNOHANG';
use strict;my $max_proc_pool = 1500;
my $max_worker_cycle = 10;my $quit = 0;
my (%childs, $i, $child);
my $cnt_worker;
#Обработка сигнала завершения дочернего процесса
sub sig_child {
my $child;
while(($child = waitpid(-1, WNOHANG)) > 0) {
my $id = $childs{$child};
if(defined($id)) {
#можно пометить процесс как убитый, а можно и ничего не делать
#$childs{$child} = 0;
print "Kiled child id $id, PID($child)\n";
} else {
print "Kiled unknown child PID($child)\n";
}
$cnt_worker--;
}
}
$SIG{PIPE} = 'IGNORE';
$SIG{CHLD} = 'sig_child';
#может быть здесь стоит убить порожденные процессы ?
$SIG{TERM} = $SIG{INT} = sub{$quit++};
#Порождаем процессы которые будут выполнять основную работу и докладывать "хозяину"
pipe(READER, WRITER) or die "pipe no good: $!";
$| = 1;
for($i = 0; $i < $max_proc_pool; $i++) {
$child = fork();
die "Can't fork: $!" unless defined $child;
if ($child == 0) { #Work inchild process
do_child();
exit(0);
}
$childs{$child} = $i;
print "Build child pid $child id $i\n";
}
close WRITER;print "I build $i worker\n";
$cnt_worker = $i;#Начнем обработку "докладов" от процессов
my $in = "";
my ($mess, $id);
while(!$quit and ($cnt_worker > 0) and defined ($in = <READER>)){
chomp $in;
($child,$mess) = split(/:/,$in);
$id = $childs{$child};
print "Parent: child id '$id' pid($child) - report: $mess\n";
#sleep 1;
}
#Определим причину по которой завершилась программа
if($quit) {
print "Exit by quit = $quit\n";
print "cnt_worker is $cnt_worker\n";
}if($cnt_worker <= 0) {
print "Exit by all childs ended!\n";
print "quit is $quit\n";
print "cnt_worker is $cnt_worker\n";
}if(!defined($in)) {
print "Exit by undef 'input' variable!\n";
print "quit is $quit\n";
print "cnt_worker is $cnt_worker\n";
}
print "--------------- A parent End print---------------------\n";
exit(0);
#Процедура в которой выполняется работа дочерним процессом
sub do_child {
close READER;
my $quit_child = 0;
$SIG{TERM} = $SIG{INT} = sub{$quit_child++};
sleep(1);
select WRITER; $| = 1;
select STDOUT;
for(my $i = 0; $i < $max_worker_cycle; $i++) {
print WRITER "$$:$i\n";
sleep(1);
if($quit_child > 0) {
print "child $$ terminated!!!\n";
close WRITER;
exit(0);
}
}
close WRITER;
print "child PID $$ ended!\n";
}
потрясающе. полет мысли впечатлил. спасибо за код и комментарии