El módulo Coro::Event provee facilidades para la gestión de eventos con una filosofía similar a la de Event, pero de manera que sea compatible con el manejo de corutinas. La principal diferencia está en que no se especifica una función de callback. El programa deberá crear las corutinas necesarias y después llamar a Coro::Event::loop .
El siguiente ejemplo resuelve los nombres de una subred dada:
pp2@nereida:~/src/perl/coro$ event.pl network (DDD.DDD.DDD) | quit> 213.246.239 NETWORK 213.246.239: 213.246.239.43 => mail.bopsys.be 213.246.239.58 => mail.keyware.com 213.246.239.236 => mail.anl-plastics.be network (DDD.DDD.DDD) | quit> q pp2@nereida:~/src/perl/coro$
pp2@nereida:~/src/perl/coro$ cat -n event.pl 1 #!/usr/bin/perl 2 use warnings; 3 use strict; 4 5 use Coro; 6 use Socket; 7 use Coro::Event; 8 use Coro::Util; 9 use Coro::Debug; 10 11 sub dns { 12 my $network = shift; 13 14 my @pid; 15 for my $x (1..255) { 16 my $coro; 17 push @pid, $coro = async { 18 my $addr = "$network.$x"; 19 my $name = scalar(gethostbyaddr(inet_aton($addr), AF_INET)); 20 return unless $name; 21 22 #print "$addr => $name\n"; 23 terminate [ $addr => $name ]; 24 }; 25 $coro->desc("dns of $network.$x"); 26 } 27 #Coro::Debug::command('ps'); 28 return @pid; 29 } 30 31 my $stdin = Coro::Handle->new_from_fh(\*STDIN); 32 33 local $SIG{PIPE} = 'IGNORE'; 34 35 STDOUT->autoflush(1); 36 while() { 37 print "network (DDD.DDD.DDD) | quit> "; 38 my $net = <$stdin>; # before this line #w is undef 39 chomp $net; 40 41 if ($net =~ /^\d+\.\d+\.\d+$/) { 42 my @pids = dns($net); 43 44 # Watch the coroutines 45 #Coro::Debug::session(\*STDOUT); 46 #Coro::Debug::command('ps'); 47 48 # Synchronize, collect and output results 49 my @results; 50 push @results, $_->join for @pids; 51 52 print "NETWORK $net:\n"; 53 printf("%15s => %s\n", @$_) for @results; 54 55 } elsif ($net =~ /qu?i?t?/) { 56 exit; 57 } elsif ($net !~ /^\s*$/) { 58 print "unknown command '$net', either 'dns' or 'quit'\n"; 59 } 60 }
event.pl
anterior
descomente las llamadas a funciones de Coro::Debug. Lea la
documentación del módulo Coro::Debug.
Descomentar la llamada a session nos permitirá ejecutar comandos de depuración interactivamente:
pp2@nereida:~/src/perl/coro$ event.pl network (DDD.DDD.DDD) | quit> 87.30.69 coro debug session. use help for more info > ps PID SS RSS USES Description Where 136064756 US 18k 2 [main::] [./event.pl:45] 136064900 -- 1388 168 [coro manager] [/usr/local/lib/perl/5.8.8/Coro.pm:177] 136065140 N- 52 0 [unblock_sub scheduler] - 136974144 -- 1420 170 [Event idle process] [/usr/local/lib/perl/5.8.8/Coro/Event.pm:211] 138396120 -- 2008 2 dns of 87.30.69.157 [./event.pl:19] 138396876 -- 2008 2 dns of 87.30.69.160 [./event.pl:19] 138397128 -- 2008 2 dns of 87.30.69.161 [./event.pl:19] 138398136 -- 2008 2 dns of 87.30.69.165 [./event.pl:19] ......... -- .... 2 dns of ............ [./event.pl:19] ......... -- 1816 1 dns of ............ [./event.pl:19] 138496856 -- 1816 1 dns of 87.30.69.255 [./event.pl:19] >
La función inet_aton toma una dirección IP con notación de punto y la empaqueta:
lhp@nereida:~/Lperl/src/perl_networking/ch3$ cat -n name_trans.pl 1 #!/usr/bin/perl 2 use strict; 3 use Socket; 4 my $ADDR_PAT = /^\d+\.\d+\.\d+\.\d+$/; 5 6 while (<>) { 7 chomp; 8 die "$_: Not a valid address" unless /$ADDR_PAT/o; 9 my $name = gethostbyaddr(inet_aton($_),AF_INET); 10 $name ||= '?'; 11 print "$_ => $name\n"; 12 }
En un contexto escalar la función gethostbyaddr
devuelve el nombre lógico que se corresponden con la dirección IP
empaquetada. Si la búsqueda fracasa devuelve undef
.
Toma dos argumentos: la dirección empaquetada y la familia de direcciones
(habitualmente AF_INET
).
En un contexto de lista devuelve cinco elementos:
DB<1> use Socket DB<2> x gethostbyaddr(inet_aton('209.85.135.103'), AF_INET) 0 'mu-in-f103.google.com' # Nombre Canonico 1 '' # lista de alias 2 2 # Tipo AF_INET 3 4 # Longitud de la dirección 4 'ÑUg' # Dirección empaquetada
Coro::Util sobreescribe las funciones gethostbyname , gethostbyaddr y inet_aton haciendolas no bloqueantes.