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 Processo B input stream TCP socket TCP socket output stream infromb outtob Socket IP network Socket outtoa infroma output input stream stream 2: Application Layer 7
Programmazione con le socket TCP Esempio di applicazione client-server: 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 tastiera Processo Client input stream output stream outtoserve client clientsocke TCP socket to network infromuse terminale infromserve input stream from network TCP socket 2: Application Layer 8
Interazione Client/server con le socket : TCP Server (in esecuzione su hostid) Crea una socket, port=x, per le richieste in arrivo, e aspetta welcomesocket = ServerSocket(x) Client 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 { Crea un input stream Crea la socket client, Connessa al server Crea un output stream Connesso alla socket public static void main(string argv[]) throws Exception { String sentence; String modifiedsentence; 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 Manda una riga al server Legge una riga dal server BufferedReader infromserver = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); sentence = infromuser.readline(); outtoserver.writebytes(sentence + '\n'); 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 Legge una riga dalla socket DataOutputStream outtoclient = new DataOutputStream(connectionSocket.getOutputStream()); 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 UDP: i dati ricevuti possono essere persi o ricevuti fuori ordine Punto di vista dell applicazione: UDP fornisce un trasferimento non affidabile di gruppi di byte ( datagrammi ) tra client e server 2: Application Layer 15
Interazione Client/server con le socket: UDP Server (in esecuzione su hostid) Client Crea una socket, port=x, per le richieste in arrivo: serversocket = DatagramSocket(x) Legge le richieste da serversocket Crea una socket, clientsocket = DatagramSocket() Crea, indirizza (hostid, port=x) Invia il datagramma di richiesta usando clientsocket Scrive le risposte su serversocket Specificando indirizzo IP e porta del client Legge la risposta da clientsocket chiude clientsocket 2: Application Layer 16
Esempio: Java client (UDP) keyboard monitor Client Process process Output: invia un pacchetto (TCP mandava un flusso di byte ) input stream UDP packet infromuser sendpacket receivepacket client UDP clientsocket socket UDP packet UDP socket Input: riceve un pacchetto (TCP riceveva un flusso di byte ) to network 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 Crea spazio per il datagramma ricevuto Rieceve il datagramma 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]; while(true) { DatagramPacket receivepacket = new DatagramPacket(receiveData, receivedata.length); serversocket.receive(receivepacket); 2: Application Layer 20
Esempio : Java server (UDP), cont Determina indirizzo IP e porta del mittente String sentence = new String(receivePacket.getData()); InetAddress IPAddress = receivepacket.getaddress(); int port = receivepacket.getport(); Crea un datagramma da mandare al client Scrive il datagramma Sulla socket String capitalizedsentence = sentence.touppercase(); senddata = capitalizedsentence.getbytes(); DatagramPacket sendpacket = new DatagramPacket(sendData, senddata.length, IPAddress, port); serversocket.send(sendpacket); Fine del loop while torna all inizio e attendi un altro datagramma 2: Application Layer 21