Due computer collegati tramite una rete locale possono comunicare tra loro nella modalità Client/Server o nella modalità peer to peer.
I computer sono dotati di una scheda di rete che si collega alla LAN. I programmi, che intendono affidare alla scheda di rete i messaggi da trasferire sulla rete, preparano una richiesta e, attraverso il socket, la consegnano al livello Trasporto.
Un socket rappresenta un connettore software uscente dal livello Applicazione che si innesta sul livello Trasporto, consentendo un trasferimento bidirezionale.
Il programma Server riceve i messaggi, li esamina e prepara una risposta. Affinchè i due sistemi, mittente e destinatario, possano comunicare appoggiandosi sul protocollo TCP devono stabilire una connessione:
Il client invia al server un pacchetto di tipo Richiesta Apertura Connessione
la rete smista il pacchetto e lo consegna all'host di destinazione, nel quale, il livello Trasporto consegna la richiesta al processo destinatario.
il server, se è disponibile, invia un pacchetto di risposta per accettare la connessione.
il pacchetto viaggia attraverso la rete locale e viene consegnato al mittente.
A questo punto la connessione è stata stabilita e i pacchetti contenenti i dati da trasferire tra i due interlocutori transiteranno sulla connessione. Secondo il modello TCP la connessione è rappresentata da un insieme di variabili gestite dal protocollo di Trasporto. Nelle architetture di rete ATM, invece, la connessione su cui viaggiano i pacchetti è realizzata e mantenuta dai dispositivi di rete (router) che partecipano allo smistamento dei pacchetti (ved. Circuito Virtuale).
Il programma seguente crea un socket, poi resta in ascolto sulla porta 9090. Dopo la ricezione di una richiesta di apertura connessione, il programma invia la risposta di accettazione, un messaggio di avvenuta connessione, subito dopo, invia il messaggio di chiusura e rilascio della connessione.
La richiesta di connessione può essere inviata da un'applicazione client oppure da un terminale virtuale, come telnet.
Avviare NetBeans.
Creare un nuovo progetto (File → New Project)
Nella casella Categories: scegliere Java e nella casella Projects: scegliere Java Application.
Nella casella Project Name scrivere: Server, lasciare non spuntata la casella "Use Dedicated Folder for Storing Libraries", e togliere la marca di spunta alla casella Create Main Class.
Clic destro sul nodo Source Package del progetto Server che compare nella casella Projects e, dal menu contestuale, scegliere New → JFrame Form …. La presenza dei puntini accanto alla voce di menu indica che si aprirà un riquadro di dialogo.
Nella casella Class Name scrivere frmServer e assegnare il nome al package: my.server.
Clic sul pulsante Finish
Progetto del layout per l'interfaccia grafica.
Fare clic sul componente Panel e posizionarlo nella parte superiore del Frame. Ridimensionarlo in modo da coprire tutta la larghezza del frame.
Nella casella delle proprietà del pannello fare clic sul pulsante con il simbolo dei puntini (…) in fondo alla riga Border.
Si apre un riquadro che propone vari stili del bordo. Scegliere TitledBorder. Nella parte inferiore del riquadro compaiono le proprietà per lo stile del bordo che si è scelto. Modificare la proprietà Title in Server. Sulla riga Border scegliere il valore LineBorder. Premere il pulsante Ok per chiudere il riquadro di scelta dello stile del bordo e premere Ok per chiudere il riquadro delle proprietà.
Aggiungere un pulsante. Nel pannello delle proprietà modificare la proprietà Text: Ascolta.
Aprire la scheda Source della classe frmServer.java.
Nell'intestazione del programma, prima della dichiarazione della classe, inserire le seguenti linee:
import java.net.*;
import java.io.IOException;
import java.io.PrintWriter;
Commenti:
La libreria IOException viene utilizzata perchè occorre gestire le eccezioni, ovvero segnalazioni di errore al sistema operativo da parte del programma.
La libreria PrintWriter gestisce il flusso di caratteri su un canale di comunicazione collegato ad una periferica (ved. figura).
Le classi che consentono di aggiungere ai programmi le funzionalità di comunicazione sulla rete sono disponibili nella libreria java.net
All'interno della classe Server, prima del metodo main, definire il metodo ascolta:
public void ascolta() throws IOException {
ServerSocket server = new ServerSocket(9090);
try {
Socket socket = server.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println("Connessione avvenuta");
} finally {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println("Connessione chiusa");
socket.close();
}
} finally {
server.close();
}
}
Commenti:
La classe ServerSocket fornisce il gestore dell'evento richiesta apertura connessione. Viene creato un oggetto denominato "server", inizializzato mediante il costruttore della classe ServerSocket. Gli viene assegnata la porta 9090.
Le operazioni di comunicazione con le periferiche sono svolte all'interno di una sezione "try … catch … finally". Se si verifica un errore nella sezione try, questo viene gestito tramite le istruzioni nella sezione catch. In ogni caso vengono svolte le istruzioni della sezione finally. Ad esempio, se la porta è libera il socket viene creato, altrimenti si verifica un errore.
L'istruzione server.accept() mette l'applicazione in ascolto sul socket 9090. Quando arriva una richiesta di connessione, il server risponde con un pacchetto di accettazione e crea un oggetto socket contenente i parametri per gestire la connessione con il client da cui ha ricevuto il pacchetto di apertura connessione. L'oggetto socket, in particolare, conterrà l'indirizzo del client e la porta su cui è in ascolto. In pratica, l'applicazione crea due socket: il server aspetta richieste di connessione, mediante il metodo server.accept(), quando ne riceve una, crea un oggetto socket con cui comunicare con il client.
L'oggetto out, di classe PrintWriter, è un canale di comunicazione tra l'applicazione e il socket.
Aprire la scheda Design. Selezionare il pulsante. Nella finestra delle proprietà aprire la scheda Events ed associare il gestore di evento actionPerformed al pulsante.
Nella scheda Source completare il gestore di evento:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
jLabel1.setText("in ascolto");
ascolta();
} catch(IOException e) {
jLabel1.setText("errore");}
}
Nel menu Run scegliere la voce Clean and Build Project.
Se non ci sono errori, nella cartella del progetto aprire la cartella dist e fare doppio clic sul file Server.jar
Se l'applicazione Server.jar non si apre, tornare all'IDE di NetBeans, fare clic con il tasto destro sul nome del progetto e, dal menu contestuale, scegliere la voce Properties. Nella finestra delle proprietà fare clic sul pulsante Browse sulla riga: "Main Class" e selezionare la classe proposta (nome del package seguito dal nome del Frame).
Si aprirà la finestra dell'applicazione. Per verificare il funzionamento del programma si può usare telnet ed aprire una connessione verso l'host all'indirizzo IP: 127.0.0.1, in ascolto sulla porta 9090. Nella finestra del programma telnet si devono leggere le risposte inviate dal server, in seguito alla richiesta di apertura connessione.
Creare un nuovo progetto. Denominarlo Client.
Aggiungere un Frame al progetto.
Collocare un panel sul Frame
Aggiungere una label ed un pulsante sul pannello. Modificare la didascalia del pulsante: Connetti. Anche a questo pulsante aggiungere un gestore di evento:
try {
Socket s = new Socket("127.0.0.1", 9090);
BufferedReader input =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String risposta = input.readLine();
jLabel1.setText(risposta);
} catch(IOException e) {}
Il programma Client crea un socket richiamando il costruttore della classe socket. Al costruttore viene specificato l'indirizzo dell'host a cui connettersi e il numero di porta dell'applicazione in ascolto su quell'host. Il numero di porta rappresenta un identificativo del programma con cui il socket del client entra in comunicazione. Cioè sullo stesso host server si possono creare più socket, ognuno in comunicazione con un client.
Nell'intestazione del file sorgente aggiungere le righe:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
Costruire l'applicazione (Clean and Build) e verificarne il funzionamento, dopo aver prima lanciato l'applicazione server.