Gestione di socket

Da Hacknowledge.

La gestione di socket in Perl è estremamente semplice e immediata rispetto a quella di molti altri linguaggi di programmazione, caratteristica che lo ha reso un linguaggio estremamente usato per la creazione di script per la comunicazione client/server. In Perl basta infatti usare il modulo IO::Socket e inizializzare un oggetto di questo tipo. In molti casi basta specificare l'host a cui ci si vuole connettere, la porta e il protocollo di trasporto per poter usare un socket bidirezionale perfettamente funzionante con l'host in questione. Creato il socket, per leggervi e scriverci su basta usare i normali metodi usati per la lettura e la scrittura su file (print per la scrittura, <SOCK_NAME> per la lettura). Ecco un esempio pratico di script in Perl che richiede l'home page ad un web server inviando una richiesta HTTP e stampa il risultato su stdout:

#!/usr/bin/perl
 
use IO::Socket;
 
$srv=shift or die "Usage: perl script.pl <web_server>\n";
 
# Inizializzo il mio oggetto -> host, porta e protocollo di trasporto
my $sock = new IO::Socket::INET(
        PeerHost => $srv,
        PeerPort => '80',
        Proto => 'tcp',
);
 
# Controllo eventuali errori nella creazione
die "Socket not created: $!\n" unless $sock;
 
# Scrivo la richiesta HTTP su socket
print $sock "GET /\n\n";
 
# Finché il server ha da inviarmi qualcosa, lo scrivo su stdout
while (<$sock>)  {
        print $_;
}
 
# Chiudo il socket
close($sock);

Semplice e indolore. Ecco invece come implementare un potenziale server in ascolto su una porta arbitraria, che legge una riga inviata dal client e la stampa su stdout:

#!/usr/bin/perl
 
use IO::Socket;
 
# Inizializzo indirizzo locale, porta su cui stare in ascolto, protocollo di trasporto e
# proprietà del socket (listen=max un client per volta, ri-uso del socket==true)
my $sock = new IO::Socket::INET(
     LocalHost => '127.0.0.1',
     LocalPort => '4444',
     Proto => 'tcp',
     Listen => 1,
     Reuse => 1,
);
 
# Controllo eventuali errori
die "Impossibile creare il socket: $!\n" unless $sock;
 
# Creo un nuovo socket per accettare le connessioni dal client
my $new_sd=$sock->accept();
 
# Finché il client ha righe da inviare, le scrivo su stdout
while (<$new_sd>)  {
     print "Il client ha inviato $_\n";
}
 
# Chiudo il socket
close ($sock);

Ed ecco un semplice client che sfrutta questo server:

#!/usr/bin/perl
 
use IO::Socket;
 
$host=shift or die "Usage: perl client.pl <host> <stringa>";
$buff=shift or die "Usage: perl client.pl <host> <stringa>";
 
my $sock = new IO::Socket::INET(
        PeerAddr => $host,
        PeerPort => '4444',
        Proto => 'tcp',
);
 
die "Impossibile creare il socket: $!\n" unless $sock;
 
print $sock $buff;
close($sock);

Per completezza, riporto tutti i possibili parametri settabili all'interno di un oggetto di tipo IO::Socket::INET (fonte: documentazione Perl):

  PeerAddr	Remote host address          <hostname>[:<port>]
  PeerHost	Synonym for PeerAddr
  PeerPort	Remote port or service       <service>[(<no>)] | <no>
  LocalAddr	Local host bind	address      hostname[:port]
  LocalHost	Synonym for LocalAddr
  LocalPort	Local host bind	port         <service>[(<no>)] | <no>
  Proto	Protocol name (or number)    "tcp" | "udp" | ...
  Type	Socket type                  SOCK_STREAM | SOCK_DGRAM | ...
  Listen	Queue size for listen
  ReuseAddr	Set SO_REUSEADDR before binding
  Reuse	Set SO_REUSEADDR before binding (deprecated, prefer ReuseAddr)
  ReusePort	Set SO_REUSEPORT before binding
  Broadcast	Set SO_BROADCAST before binding
  Timeout	Timeout	value for various operations
  MultiHomed  Try all addresses for multi-homed hosts
  Blocking    Determine if connection will be blocking mode
Strumenti personali