El programa que sigue resuelve los nombres de máquinas a su direccion IP:
lhp@nereida:~/Lperl/src/perl_networking/ch3$ ip_trans.pl www.google.com www.google.com => 209.85.135.103 www.yahoo.com www.yahoo.com => 69.147.114.210 www.upc.es www.upc.es => 147.83.194.21
lhp@nereida:~/Lperl/src/perl_networking/ch3$ cat -n ip_trans.pl 1 #!/usr/bin/perl 2 use strict; 3 use Socket; 4 5 while (<>) { 6 chomp; 7 my $packed_address = gethostbyname($_); 8 unless ($packed_address) { 9 print "$_ => ?\n"; 10 next; 11 } 12 my $dotted_quad = inet_ntoa($packed_address); 13 print "$_ => $dotted_quad\n"; 14 }
La llamada $packed_address = gethostbyname($name)
devuelve - en un contexto escalar-
un escalar que contiene una estructura empaquetada que describe la dirección.
En un contexto de lista gethostbyname
devuelve 5 elementos:
pp2@nereida:/tmp/UnixProcess-Composition-Simple-0.01/script$ perl -wde 0 main::(-e:1): 0 DB<1> @a = gethostbyname('www.google.com') DB<2> x @a 0 'www.l.google.com' # canonical hostname: nombre oficial 1 'www.google.com' # alias (separados por espacios) 2 2 # tipo de dirección: AF_INET 3 4 # longitud de la dirección empaquetada 4 'ÑUg' # dirección empaquetada 0 5 'ÑUh' # dirección empaquetada 1 6 'ÑUc' # dirección empaquetada 2 7 'ÑU' # dirección empaquetada 3
La función pack recibe una cadena de formato y una lista de argumentos y empaqueta dichos argumentos según la descripción dada en la cadena de formato. La cadena de formato esta compuesta a partir de letras que denotan diversos tipos y representación:
Formato | Descripción |
c,C | char (entero de 8 bits). |
s,S | short, 16 bits. |
l,L | long, 32 bits. |
q,Q | quad (64 bits). |
i,I | entero con signo, formato nativo. |
n,N | Un valor de 16 ó 32 bits (big-endian). |
v,V | Un valor de 16 ó 32 bits (orden "VAX" o little-endian). |
a,A | Cadena rellena con caracteres nulos/espacios. |
b,B | Cadena de bits con órdenes de bits ascendiente o descendiente. |
h,H | Cadena hexadecimal, Nibble alto o bajo primero. |
Z | Cadena terminada con un carácter nulo. |
Ejemplos:
DB<1> $b = pack "c s l", 31, 1000, 4320033 DB<2> ($c, $s, $n) = unpack "c s l", $b DB<4> x ($c, $s, $n) 0 31 1 1000 2 4320033La letra de formato puede cualificarse con un número para indicar repetición:
DB<1> $b = pack "c2 s3 c5", 31, 24, 1000..1002, ord('A')..ord('E') DB<2> x unpack "c2 s3 c5", $b 0 31 1 24 2 1000 3 1001 4 1002 5 65 6 66 7 67 8 68 9 69En los formatos alfabéticos (como
a8
) el número no indica repetición.
Indica que la cadena "a"
se rellena con caracteres nulos hasta tener
tamaño 8:
DB<1> $b = pack "a8", "hola" DB<2> x $b 0 "hola\c@\c@\c@\c@" DB<3> p $b holaEs posible cualificar la letra con un asterisco para indicar que el formato se puede usar tantas veces como se quiera para empaquetar los restantes items:
DB<5> $b = pack "s*", 31, 1000, 432, 27 DB<6> @a = unpack "s*", $b DB<7> x @a 0 31 1 1000 2 432 3 27
El dominio de un socket define la familia de protocolos y esquemas de dirección que serán soportados por el socket.
Ejemplo:
DB<3> use Socket DB<4> @a = (AF_UNIX, AF_INET); print "@a" 1 2
La subrutina inet_ntoa toma la dirección
empaquetada $packed_address
y la convierte
en el clásico formato de cuadrupla separada por puntos.
DB<5> $p = pack 'C4', split /\./, '209.85.135.103' DB<6> p join '.', unpack 'C4', $p 209.85.135.103 DB<30> x inet_ntoa($p) 0 '209.85.135.103'
El programa que sigue realiza la conversión desde una IP a
su nombre lógico mediante la función gethostbyaddr
.
lhp@nereida:~/Lperl/src/perl_networking/ch3$ name_trans.pl 209.85.135.103 209.85.135.103 => mu-in-f103.google.com 69.147.114.210 69.147.114.210 => f1.www.vip.re3.yahoo.com 147.83.194.21 147.83.194.21 => upc.edu
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
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 }