✦ Introduzione
✦ Connessioni TCP lato client: la classe
Socket
✦ Connessioni TCP lato server: la classe
ServerSocket
✦ Struttura di un server multi-threaded
IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla Cresima
Lezione 3: Connessioni TCP
1. Lezione 3: Connessioni
TCP
Corso di Programmazione in Rete
Laurea Magistrale in Ing. Informatica
Università degli Studi di Salerno
1
2. Outline
✦ Introduzione
✦ Connessioni TCP lato client: la classe
Socket
✦ Connessioni TCP lato server: la classe
ServerSocket
✦ Struttura di un server multi-threaded
2
3. Introduzione
✦ I protocolli di livello 4 (transport) più
usati su internet:
• TCP: connection oriented
• UDP: datagram oriented
3
4. Socket
✦ Le API per i protocolli TCP e UDP usano il
concetto di “socket” (“presa”) per
specificare i due estremi del canale di
comunicazione
✦ I socket attivi su una macchina per un
determinato protocollo sono identificati
attraverso un numero a 16 bit (port
number)
• le applicazioni più comuni hanno un “well-known”
port number usato per default
• nei sistemi Unix-like i numeri 0-1023 richiedono i
privilegi di amministratore del sistema
4
5. Socket TCP
✦ Per il protocollo TCP (connection oriented)
i due socket che devono comunicare
devono essere connessi
• Una delle due parti inizia la connessione (client)
• L’altra parte deve essere in attesa di una richiesta
di connessione (server); quando arriva una
richiesta di connessione, il server deve accettare
la richiesta per stabilire il collegamento
✦ L’instaurazione della connessione è
un’operazione relativamente costosa in
termini di tempo
5
6. Socket TCP in Java
✦ Le classi principali sono nel package
java.net
✦ La classe che rappresenta un socket TCP
dal punto di vista del client è Socket
6
7. Creazione di un Socket
✦ Costruttore:
• Socket(String hostAddress, int port)
✦ i parametri specificano l’indirizzo del
socket a cui il socket creato si deve
connettere
• hostAddress può essere l’indirizzo IP in forma
“dotted” (es. “193.205.164.3”) o l’indirizzo
simbolico (es. “www.unisa.it”)
✦ il costruttore solleva una IOException in
caso di problemi
7
8. Uso di un client socket
✦ I seguenti metodi consentono di ottenere
input/output stream associati al socket:
• InputStream getInputStream()
• OutputStream getOutputStream()
✦ Usando questi stream in congiunzione
con le altre classi di I/O è possibile
inviare/ricevere dati attraverso la
connessione TCP
✦ Al termine dell’uso il socket deve essere
chiuso col metodo close
8
9. Esempio
✦ Vogliamo realizzare un programma che
apra una connessione TCP con un server,
invii una stringa e legga una stringa di
risposta dal server
9
10. Esempio
✦ Innanzitutto, creiamo il socket:
import java.io.*;
import java.net.*;
public class EchoClient {
public static final int PORT=7777;
public static void main(String args[]) throws IOException {
Socket sock=new Socket(args[0], PORT);
10
11. Esempio
✦ Quindi inviamo la stringa, usando un
PrintWriter:
OutputStream os=sock.getOutputStream();
Writer wr=new OutputStreamWriter(os, "UTF-8");
PrintWriter prw=new PrintWriter(wr);
prw.println("Hello, world");
prw.flush();
Nota: il metodo flush() forza l’invio di
eventuali buffer in memoria
11
12. Esempio
✦ Infine, leggiamo la risposta dal server
usando un BufferedReader:
InputStream is=sock.getInputStream();
Reader rd=new InputStreamReader(is, "UTF-8");
BufferedReader brd=new BufferedReader(rd);
String answer=brd.readLine();
System.out.println(answer);
sock.close();
}
}
12
13. Socket lato server
✦ La creazione di socket TCP dal lato del
server si effettua attraverso la classe
ServerSocket
✦ Un ServerSocket rappresenta una
“fabbrica” (“factory”) di socket: al
momento in cui viene accettata una
richiesta di connessione da un client, il
ServerSocket crea un Socket attraverso il
quale avviene la comunicazione
13
14. Creazione di ServerSocket
✦ Costruttore:
• ServerSocket(int port)
✦ Il ServerSocket è in attesa di richieste sul
port specificato
✦ Anche le operazioni su ServerSocket
possono lanciare IOException
14
15. Attesa di una connessione
✦ Il ServerSocket si mette in attesa della
prossima richiesta e la accetta
instaurando una connessione con il
metodo:
• Socket accept();
✦ Il Socket restituito è utilizzabile per
comunicare con il client
15
16. Esempio
✦ Per completare l’esempio precedente,
realizziamo un server che accetti una
connessione, legga una stringa attraverso
il socket e invii alla connessione due volte
la stessa stringa
16
17. Esempio
✦ Creiamo il ServerSocket e accettiamo la
connessione:
import java.io.*;
import java.net.*;
public class EchoServer {
public static final int PORT=7777;
public static void main(String args[]) throws IOException {
ServerSocket serv=new ServerSocket(PORT);
Socket sock=serv.accept();
17
18. Esempio
✦ Leggiamo una stringa:
BufferedReader brd=new BufferedReader(
new InputStreamReader(
sock.getInputStream(), "UTF-8"));
String s=brd.readLine();
18
19. Esempio
✦ Inviamo la risposta:
PrintWriter prw=new PrintWriter(
new OutputStreamWriter(
sock.getOutputStream(), "UTF-8"));
prw.print(s);
prw.println(s);
prw.flush();
sock.close();
}
}
19
20. Server multi-threaded
✦ Di solito un server deve servire più di una
singola richiesta
✦ Il modo più semplice è creare un thread
per ogni nuova richiesta di connessione
• il thread principale esegue accept() in un ciclo
• i thread creati per ogni richiesta gestiscono la
comunicazione con il client
20
21. Esempio
✦ Modifichiamo il server precedente in
modo da poter servire più richieste
21
22. Esempio
✦ Per cominciare, definiamo la classe:
import java.io.*;
import java.net.*;
public class ThreadedEchoServer implements Runnable {
public static final int PORT=7777;
private Socket sock;
public ThreadedEchoServer(Socket s) {
sock=s;
}
22
23. Esempio
✦ Nel main creiamo i thread:
public static void main(String args[]) throws IOException {
ServerSocket serv=new ServerSocket(PORT);
while (true) {
Socket sock=serv.accept();
ThreadedEchoServer server=new ThreadedEchoServer(sock);
Thread t=new Thread(server);
t.start();
}
}
23
24. Esempio
✦ Il metodo run contiene la gestione di una
singola connessione
public void run() {
try {
BufferedReader brd=new BufferedReader(
new InputStreamReader(
sock.getInputStream(), "UTF-8"));
String s=brd.readLine();
PrintWriter prw=new PrintWriter(
new OutputStreamWriter(
sock.getOutputStream(), "UTF-8"));
prw.print(s);
prw.println(s);
prw.flush();
} catch (IOException exc) {
System.out.println("Eccezione I/O:" + exc);
exc.printStackTrace();
} finally {
try { sock.close(); }
catch (IOException exc2) { }
}
}
}
24