Programmazione.it v6.4
Ciao, per farti riconoscere devi fare il login. Non ti sei ancora iscritto? Che aspetti, registrati adesso!
Info Pubblicità Collabora Autori Sottoscrizioni Preferiti Bozze Scheda personale Privacy Archivio Libri Corsi per principianti Forum
Corso su Ruby: programmazione socket
Scritto da Satish Talim il 03-07-2007 ore 10:11
Intel Parallel Studio XE
Possiamo sviluppare applicazioni di rete basate su socket utilizzando il linguaggio Ruby. È necessario avere una conoscenza di base dei socket stile BSD (Berkley Software Distribution). Attualmente, possiamo tranquillamente parlare genericamente di socket, mentre in passato sarebbe stato corretto parlare di socket BSD poiché erano presenti molte API per socket in competizione tra loro. Infine, l'API per socket BSD ha avuto la meglio nel mondo UNIX/POSIX. La maggior parte degli sviluppatori []*nix[/], che ha a che fare con networking, usa socket in stile BSD. Avendo pratica nella programmazione di connessioni di rete in C o C++, è sorprendentemente facile programmare le stesse cose in Ruby.

Parliamo un po' delle basi del networking. Le nostre osservazioni sul networking si focalizzano sulla relazione client-server. Il client richiede che venga eseguita una certa operazione, e il server realizza l'azione e invia una risposta al client. Un’implementazione comune del modello richiesta-risposta è l'interazione tra i browser e i server Web. Quando un utente seleziona un sito Web attraverso un browser (l'applicazione client), viene inviata una richiesta al server Web appropriato (l'applicazione server); il server normalmente risponde al client inviando la pagina HTML appropriata.

Una porta non è un dispositivo fisico, ma un’astrazione per facilitare la comunicazione tra un server e il client. Le porte sono descritte da un valore intero a 16 bit. Quindi, una macchina può avere fino ad un massimo di 65535 numeri di porte (da 0 a 65535). I numeri di porta sono suddivisi in tre intervalli: le Well Known Port, le Registered Port e le Dynamic o Private Port. Le Well Known Port sono quelle da 0 a 1023 (per esempio: la porta 80 è per HTTP, la 25 per SMTP e così via). Le Registered Port sono dal 1024 a 49151. Le Dynamic o Private Port sono quelle da 49152 a 65535.

Gli indirizzi Internet sono gli indirizzi numerici di un host e sono formati da 4 byte come 132.162.4.102. L'indirizzo 127.0.0.1 (localhost) è un indirizzo speciale, detto indirizzo di loopback, e denota la macchina locale.

Un socket rappresenta una singola connessione tra due applicazioni di rete. Queste due applicazioni nominalmente sono eseguite su due computer differenti, ma i socket possono essere utilizzati anche per la comunicazione interprocesso di un singolo computer. Le applicazioni possono creare socket per comunicare tra loro. I socket sono bidirezionali, intendendo con questo che entrambi gli estremi della connessione possono sia inviare che ricevere dati.

Ruby dispone di un insieme ricco e vario di classi per i socket, che vanno dalla classe standard Socket (che riproduce l’API dei socket BSD) fino a classi più raffinate, che concentrano l'attenzione su un particolare protocollo o tipo di applicazione. La gerarchia delle classi base per i socket è mostrata nella figura seguente, tratta dal testo “Programming Ruby”:

<center>11609790762161849.jpg</center>

La classe TCPSocket offre il supporto per i socket per il protocollo TCP. Una classe di aiuto per la creazione di socket server TCP è disponibile nella classe TCPServer. Per creare un flusso socket e connetterlo ad un server, è possibile usare la classe TCPSocket.

Ora costruiremo un server e client DataOra, basato su Ruby, che mostra sul computer client la data e l'ora della locazione del server, utilizzando l’API socket di Ruby. Ecco il codice per il server Data-Ora p068dtserver.rb:
  1. <span style="font-size:1.0em">
  2. # Date Time Server - server side usando i thread
  3. # usage: ruby p068dtserver.rb
  4. require "socket"
  5. dts = TCPServer.new('localhost', 20000)
  6. loop do
  7.   Thread.start(dts.accept) do |s|
  8.     print(s, " is acceptedn")
  9.     s.write(Time.now)
  10.     print(s, " is gonen")
  11.     s.close
  12.   end
  13. end</span>

Prima di tutto viene caricata la libreria socket con il comando require. La classe TCPServer è la classe helper per la costruzione dei server socket TCP. L'istruzione
  1. <span style="font-size:1.0em">TCPServer.new('localhost', 20000)</span>
crea un nuovo socket identificato da localhost e numero. Il
  1. <span style="font-size:1.0em">Thread.start</span>
crea ed esegue un nuovo thread per lanciare le istruzioni del blocco. Qualsiasi argomento passato al
  1. <span style="font-size:1.0em">Thread.start</span>
viene passato al blocco. Il metodo
  1. <span style="font-size:1.0em">dts.accept</span>
attende una connessione su dts, e ritorna un nuovo oggetto TCPSocket connesso con il chiamante. L'iteratore
  1. <span style="font-size:1.0em">Kernel.loop</span>
chiama il blocco associato do - end per sempre (o almento fino che non si esce dal loop).

Usiamo
  1. <span style="font-size:1.0em">s.write(Time.now)</span>
per scrivere la data corrente e l'ora del server sul socket. Infine, scriviamo
  1. <span style="font-size:1.0em">s.close</span>
per chiudere un socket utilizzando il metodo close. Quest’ultimo è ereditato dalla classe IO, ma è disponibile per ciascun tipo di socket.

Visto che stiamo testando questi programmi sulla nostra macchina locale, apriamo una finestra di prompt, andiamo nella cartella che contiene il programma p068dtserver.rb e digitiamo ruby p068dtserver.rb. Il programma va in esecuzione e attende un client che si connetta sulla porta 20000.

Di seguito il codice per il client DataOra:
  1. <span style="font-size:1.0em">
  2. # Date Time Client
  3. # usage: ruby p069dtclient.rb
  4. require 'socket'
  5. sock = TCPSocket.new('127.0.0.1', 20000)
  6. str = sock.recv(100)
  7. print str
  8. sock.close</span>

Per prima cosa viene caricata la libreria socket con il comando require. L'istruzione
  1. <span style="font-size:1.0em">sock = TCPSocket.new('127.0.0.1', 20000)</span>
apre una connessione TCP verso localhost alla porta 2000. L'istruzione
  1. <span style="font-size:1.0em">str = sock.recv(100)</span>
permette di ricevere fino a 100 byte dal sock. Mostriamo la stringa data-ora ricevuta dal server e alla fine chiudiamo il socket.

"Traduzione e adattamento a cura di Francesca Beatrice Cice. La versione originale del tutorial di Satish Talim può essere trovata su rubylearning.com"
Precedente: Beginning CSS Web Development
Successiva: Breve corso sulla compressione dei file: la famiglia LZ e LZ77 (3/3)
Intervento di qwfwq del 03-07-2007 ore 13:37
Nobile
Nobile

(81 interventi)
Iscritto il 17-10-2006
scusa Francesca, ma c'è un tag di corsivo mal formattato ad inizio paragrafo...

Ne approfitto anche per farti i complimenti per questo corso!
Copyright Programmazione.it™ 1999-2013. Alcuni diritti riservati. Testata giornalistica iscritta col n. 569 presso il Tribunale di Milano in data 14/10/2002. Pagina generata in 0.299 secondi.