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