Si se especifica la opción Listen en el constructor de IO::Socket::INET el socket creado es un socket para 'escucha', esto es, se asume el lado del servidor.
bash-2.05a$ uname -a
Linux manis 2.4.20-37.7.legacysmp #1 SMP Mon Sep 27 21:38:15 EDT 2004 i686 unknown
bash-2.05a$ cat -n server.pl
1 #!/usr/local/bin/perl -w
2 use strict;
3 use IO::Socket;
4
5 $SIG{CHLD} = sub { wait(); };
6
7 my $host = shift || 'localhost';
8 my $port = shift || 1024;
9
10 my $mains =IO::Socket::INET->new(
11 LocalHost => $host,
12 LocalPort => $port,
13 Listen => 10,
14 Proto => 'tcp',
15 Reuse => 1,
16 );
17 die "Can't create socket $!\n" unless $mains;
El método accept es únicamente válido
cuando se llama a un socket en modo escucha (construido
con la opción listen ).
Obtiene la siguiente conexión de la cola y retorna la
sesión conectada al socket. Esta sesión es un socket manejador
que se utilizará para conectar con la máquina remota.
El nuevo socket hereda todo los atributos de su padre
y además está conectado.
Cuando se llama a accept en un contexto escalar retorna el socket conectado. Cuando se llama en un contexto de lista retorna una lista con dos elementos, el primero de los cuales es el socket conectado y el segundo es la dirección empaquetada del host remoto. También es posible obtener esta información haciendo uso del método peername .
18 my $news;
19 while (1) {
20 while ($news = $mains->accept()) {
21 my $pid = fork() and next;
22
23 print "**********************\n";
24 my $buf = '';
25 my $c = 1;
26 while (sysread($news, $buf, 1024)) {
27 print "'$buf'\n";
28 syswrite($news, "message $c from $host");
29 $c++;
30 }
31 exit(0);
32 }
33 }
34 close($mains);
Aquí hacemos un fork por cada cliente que se conecta.
El proceso hijo queda a la espera de mensajes de la máquina
remota hasta que esta cierra el canal.
Cuando no se especifica Listen y el tipo del socket es SOCK_STREAM
(que se deduce del protocolo usado)
el método connect es invocado.
-bash-2.05b$ uname -a
Linux millo.etsii.ull.es 2.4.22-1.2188.nptlsmp #1 SMP Wed Apr 21 20:12:56 EDT 2004 i686 i686 i386 GNU/Linux
-bash-2.05b$ cat -n client.pl
1 #!/usr/local/bin/perl -w
2 use strict;
3 use IO::Socket;
4
5 my $server = shift || 'manis';
6 my $port = shift || 1234;
7
8 my $host = $ENV{HOSTNAME};
9 my $sock = IO::Socket::INET->new(
10 PeerAddr => $server,
11 PeerPort => $port,
12 Proto => 'tcp',
13 );
14 die "Can't create socket $!\n" unless $sock;
15
16 for (1..10) {
17 syswrite($sock,"Message $_ from $host");
18 my $answer = '';
19 sysread($sock, $answer,1024);
20 print "'$answer'\n";
21 }
22 close($sock);
Una alternativa a close es el método shutdown :
$return_val = $socket->shutdown($how)Cerrará el socket incluso si existen copias en procesos hijos creados con
fork.
El argumento $how controla que mitad del socket bidireccional será cerrada.
| Valor | Descripción |
| 0 | Cierra el socket para lectura |
| 1 | Cierra el socket para escritura |
| 2 | Cierra el socket totalmente |
| Cliente en millo | Servidor en manis |
-bash-2.05b$ ./client.pl manis 1234 'message 1 from manis' 'message 2 from manis' 'message 3 from manis' 'message 4 from manis' 'message 5 from manis' 'message 6 from manis' 'message 7 from manis' 'message 8 from manis' 'message 9 from manis' 'message 10 from manis' -bash-2.05b$ |
bash-2.05a$ ./server.pl manis 1234 ********************** 'Message 1 from millo.etsii.ull.es' 'Message 2 from millo.etsii.ull.es' 'Message 3 from millo.etsii.ull.es' 'Message 4 from millo.etsii.ull.es' 'Message 5 from millo.etsii.ull.es' 'Message 6 from millo.etsii.ull.es' 'Message 7 from millo.etsii.ull.es' 'Message 8 from millo.etsii.ull.es' 'Message 9 from millo.etsii.ull.es' 'Message 10 from millo.etsii.ull.es' |
También es posible usar los métodos recv y send para la comunicación:
bash-2.05a$ cat -n server.pl
1 #!/usr/local/bin/perl -w
2 use strict;
3 use IO::Socket;
4
5 $SIG{CHLD} = sub { wait(); };
6
7 my $host = shift || 'localhost';
8 my $port = shift || 1024;
9
10 my $mains =IO::Socket::INET->new(
11 LocalHost => $host,
12 LocalPort => $port,
13 Listen => 10,
14 Proto => 'tcp',
15 Reuse => 1,
16 );
17 die "Can't create socket $!\n" unless $mains;
18 my $news;
19 while (1) {
20 while ($news = $mains->accept()) {
21 my $pid = fork() and next;
22
23 print "**********************\n";
24 my $buf = '';
25 my $c = 1;
!26 {
!27 $news->recv($buf, 1024);
!28 last unless $buf;
!29 print "'$buf'\n";
!30 $news->send("message $c from $host");
!31 $c++;
!32 redo;
!33 }
34 exit(0);
35 }
36 }
37 close($mains);
El método send tiene la sintáxis:
$bytes = $sock->send($data [,$flags, $destination])Envía
$data a la dirección especificada en $destination.
En caso de éxito retorna el número de bytes enviados.
Si falla retorna undef.
El argumento flag es un or de estas opciones
| Opción | Descripcción |
MSG_OOB |
Transmite un byte de datos urgentes |
MSG_DONTROUTE |
Sáltese las tablas de rutas |
El formato de recv es:
$address = $socket->recv($buffer, $length [,$flags])
Acepta $length bytes desde el socket y los coloca en $buffer.
Los flags tienen el mismo significado que para send.
En caso de éxito recv retorna la dirección empaquetada
del socket del transmisor. En caso de error retorna undef y la variable
$! contiene el código de error apropiado.
Realmetne, cuando se usa TCP el método recv se comporta como sysread
excepto que retorna la dirección del par. Realmente cuando se aprecia la diferencia
es en la recepción de datagramas con el protocolo UDP.
