Programmare con le Socket TCP
in java
2: Application Layer
1
Il Client contatta il server
Il Server:
ˆ Il processo server è sempre attivo in attesa di
connessioni (demone)
ˆ Crea una socket per
accettare la connessione del client
(“socket di benvenuto”, java.net.ServerSocket)
Il Client:
ˆ Crea una socket TCP locale, specificando l’indirizzo
IP e numero di porta del processo server
ˆ Quando il client crea la socket: il lato client TCP
stabilisce una connessione con il server TCP
(connessione implicita nel costruttore di
java.net.Socket)
2: Application Layer
2
Il server riceve una connessione
ˆ Quando viene contattato dal client, il TCP nel server crea
una nuova socket per far comunicare il processo server con il
nuovo client
 Un server può interagire con molti client
contemporaneamente
 Il TCP usa il numero di porta sorgente per distinguere i
pacchetti di diverse connessioni attive
(insieme all’indirizzo IP)
ˆ Dal punto di vista dell’applicazione TCP fornisce un
trasferimento di byte (un “tubo”) affidabile e ordinato tra le
socket aperte dai processi client e server
ˆ Dopo che è stata stabilita la connessione, le socket usate dal
client e dal server sono equivalenti:
 Possono inviare e ricevere dati
ˆ Un protocollo applicativo governa l’ordine in cui parlano
2: Application Layer
3
Gli Stream - gergo
ˆ Uno stream (flusso) è una sequenza di
caratteri che fluisce verso un processo o da
un processo
ˆ Un input stream è collegato a qualche
sorgente di input del processo, come la
tastiera, un file o una socket.
ˆ Un output stream è collegato a qualche
destinazione di output, come il monitor, un
file o una socket.
2: Application Layer
4
Socket in java
Package java.net
ˆ Classe java.net.Socket
ˆ
un canale di comunicazione verso un processo remoto
ˆ
Costruttore
Socket(InetAddress address, int port)
costruisce una Socket e crea una connessione al server
address,port (usata dal client)
ˆ Classe java.net.ServerSocket
un punto di accesso ad un server per nuove connessioni
ˆ
Costruttore
ServerSocket(int port)
crea una ServerSocket in attesa su una determinata porta TCP
ˆ
Metodo
Socket java.net.ServerSocket.accept()
si mette in attesa di connessioni, quando ne riceve una restituisce
la relativa Socket (usata dal server). È un metodo bloccante.
2: Application Layer
5
Socket e stream
ˆ Una volta stabilita la connessione, client e server usano
entrambi un oggetto di tipo Socket
ˆ
Metodo
InputStream java.net.Socket.getInputStream()
restituisce il flusso per leggere i dati provenienti dalla
Socket
ˆ
Metodo
OutputStream java.net.Socket.getOutputStream()
restituisce il flusso per inviare i dati verso la Socket
ˆ
Metodo
java.net.Socket.Close()
chiude la connessione TCP
2: Application Layer
6
Gli Stream delle socket TCP
ˆ Quando due processi hanno stabilito una connessione TCP usando le
socket, l’input stream della socket nel processo A è collegato
all’output stream della socket corrispondente nel processo B, e
viceversa
ˆ si realizza un canale di comunicazione interprocesso remoto
Processo A
input
Processo B
TCP
socket
TCP
socket
stream
Socket
outToB
stream
IP network
Socket
inFromB
output
outToA
inFromA
output
input
stream
stream
2: Application Layer
7
Programmazione con le socket TCP
Processo
Client
input
stream
output
stream
inFromServe
inFromUse
1) Il client legge una riga dallo
reads standard input (stream
inFromUser), e la manda al
server usando la socket
(stream outToServer )
2) Il server legge la riga dalla
socket
3) Il server converte la riga in
caratteri maiuscoli, e la
rimanda indietro al client
4) Il client legge dalla socket
(stream inFromServer ) la
riga modificata, e la stampa
terminale
outToServe
Esempio di applicazione
client-server:
tastiera
clientSocke
client
TCP socket
to network
input
stream
TCP
socket
from network
2: Application Layer
8
Interazione Client/server con le socket : TCP
Server
(in esecuzione su hostid)
Client
Crea una socket, port=x,
per le richieste in arrivo, e aspetta
welcomeSocket = ServerSocket(x)
TCP
Attende richieste di connection setup
connessione in ingresso
connectionSocket =
welcomeSocket.accept()
Legge la richiesta da
connectionSocket
Scrive la risposta su
connectionSocket
chiude
connectionSocket
Crea una socket,
Connessa a hostid, port=x
clientSocket =
Socket(hostid, port)
Invia la richiesta usando
clientSocket
Legge la risposta da
clientSocket
chiude
clientSocket
2: Application Layer
9
Esempio: Java client (TCP)
import java.io.*;
import java.net.*;
class TCPClient {
public static void main(String argv[]) throws Exception
{
String sentence;
String modifiedSentence;
Crea un
input stream
Crea la
socket client,
Connessa al server
Crea un
output stream
Connesso
alla socket
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("hostname", 6789);
DataOutputStream outToServer =
new DataOutputStream(clientSocket.getOutputStream());
2: Application Layer
10
Esempio: Java client (TCP), cont.
Crea un
input stream
Connesso alla socket
BufferedReader inFromServer =
new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
Manda una riga
al server
outToServer.writeBytes(sentence + '\n');
Legge una riga
dal server
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
clientSocket.close();
}
}
2: Application Layer
11
Esempio: Java server (TCP)
import java.io.*;
import java.net.*;
class TCPServer {
Crea una
socket di benvenuto
Sulla porta 6789
Aspetta sulla
socket di benvenuto
il contatto del client
Crea un
input stream,
connesso alla socket
public static void main(String argv[]) throws Exception
{
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
while(true) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new
InputStreamReader(connectionSocket.getInputStream()));
2: Application Layer
12
Esempio: Java server (TCP), cont
Crea un output
stream, connesso
alla socket
DataOutputStream outToClient =
new DataOutputStream(connectionSocket.getOutputStream());
Legge una riga
dalla socket
clientSentence = inFromClient.readLine();
capitalizedSentence = clientSentence.toUpperCase() + '\n';
Scrive una riga
sulla socket
outToClient.writeBytes(capitalizedSentence);
}
}
}
Fine del loop while
Torna all’inizio in attesa
di una nuova connessione
2: Application Layer
13
gestione delle eccezioni TCP
ˆ Se non è possibile effettuare una connessione TCP, il TCP informa
l’applicazione che la ha richiesta generando una eccezione, che
interrompe il flusso dell’esecuzione se non viene catturata
ˆ Una eccezione è un oggetto appartenente ad una sottoclasse di
java.lang.Exception
ˆ Le istruzioni nel blocco try possono generare eccezioni, che
vengono gestite nel blocco catch appropriato per il tipo
dell’eccezione
ˆ Una connessione fallita viene segnalata con una
java.net.ConnectException
try {
clientSocket = new Socket(argv[0], 6789);
}
catch (java.net.ConnectException e){
System.out.println("connection failed:\n" + e);
}
2: Application Layer
14
Programmazione con le socket UDP
UDP: non c’è connessione tra
client e server
ˆ Non è necessario stabilire
la connessione
ˆ Il mittente inserisce
esplicitamente l’indirizzo
IP e la porta della
destinazione in ogni
pacchetto
ˆ Il server deve estrarre
l’indirizzo IP e la porta del
mittente dal pacchetto
ricevuto
ˆ Punto di vista
dell’applicazione:
UDP fornisce un
trasferimento non
affidabile di gruppi di byte
(“datagrammi”) tra client e
server
UDP: i dati ricevuti possono
essere persi o ricevuti
fuori ordine
2: Application Layer
15
Interazione Client/server con le socket: UDP
Server (in esecuzione su hostid)
Crea una socket,
port=x, per le richieste
in arrivo:
serverSocket =
DatagramSocket(x)
Legge le richieste da
serverSocket
Scrive le risposte su
serverSocket
Specificando indirizzo IP
e porta del client
Client
Crea una socket,
clientSocket =
DatagramSocket()
Crea, indirizza (hostid, port=x)
Invia il datagramma di richiesta
usando clientSocket
Legge la risposta da
clientSocket
chiude
clientSocket
2: Application Layer
16
Esempio: Java client (UDP)
input
stream
Client
process
monitor
inFromUser
keyboard
Process
Input: riceve un
pacchetto (TCP
riceveva un “flusso
di byte”)
UDP
packet
receivePacket
pacchetto (TCP
mandava un “flusso
di byte”)
sendPacket
Output: invia un
client
UDP
clientSocket
socket
to network
UDP
packet
UDP
socket
from network
2: Application Layer
17
Esempio: Java client (UDP)
import java.io.*;
import java.net.*;
Crea un
input stream
Crea la
client socket
Traduce hostname
in un indirizzo IP
usando il DNS
class UDPClient {
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("hostname");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
2: Application Layer
18
Esempio : Java client (UDP), cont.
Crea un datagramma
con i dati,
lunghezza,
indirizzo IP, porta
Invia il datagramma
to server
Legge il
datagramma
dal server
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence =
new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
}
}
2: Application Layer
19
Esempio : Java server (UDP)
import java.io.*;
import java.net.*;
Crea una socket
datagramma
Sulla porta 9876
class UDPServer {
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
Crea spazio
per il datagramma
ricevuto
Rieceve il
datagramma
while(true)
{
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
2: Application Layer
20
Esempio : Java server (UDP), cont
String sentence = new String(receivePacket.getData());
Determina
indirizzo IP e
porta del
mittente
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
Crea un
datagramma
da mandare
al client
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress,
port);
Scrive il
datagramma
Sulla socket
serverSocket.send(sendPacket);
}
}
}
Fine del loop while
torna all’inizio e attendi
un altro datagramma
2: Application Layer
21