J0 1 Marco Ronchetti - [email protected] Java Networking TCP.

41
J0 1 Marco Ronchetti - [email protected] Java Networking TCP

Transcript of J0 1 Marco Ronchetti - [email protected] Java Networking TCP.

Page 1: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J01

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Java Networking

TCP

Page 2: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J02

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Sockets

Java supporta un accesso semplificato e

object-oriented alle sockets.

Questo rende la network comunicazione di rete sensibilmente piu’ semplice.

Molto piu’ semplice che in C++!!

Vedremo che parlare ad un altra applicazione (locale o remota) puo’ essere semplice come leggere un file o

ottenere un input da un utente.

Page 3: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J03

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Clients and Servers

Quando si scrivono network applications, e’

comune parlare di clients e servers. La distinzione e’ piuttosto vaga, ma

sostanzialmente possiamo pensare che :

•chi inizia la conversazione e’ il client. •chi accetta la richiesta di parlare e’ il server.

Per I nostri scopi, la piu’ importante differenza tra client e server e’ che il client puo’ in qualunque istante creare

una socket per iniziare una conversazione con una server application, mentre un server si deve preparare ad ascoltare in anticipo per possibili conversazioni in

arrivo.

Page 4: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J04

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Sockets

La java.net.Socket class rappresenta un singolo lato di una connessione socket indifferentemente su un client o su un server.

Inoltre, il server usa la java.net.ServerSocket class per attendere connessioni da clients. Un applicazione agente come server crea un ServerSocket object e attende, bloccato in una chiamata al suo metodo accept(), finche’ non giunge una connessione. A quel punto, il metodo accept() create un Socket object che il server usa per comunicare con il client.

Page 5: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J05

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Sockets

Un server mantiene molte conversazioni

simultaneamente.C’e’ una sola ServerSocket, ma una oggetto

Socket attivo per ogni cliente.

Page 6: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J06

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Server port

Un client ha bisogno di due informazioni per connettersi a un server su Internet: un nome di host (per recuperare l’indirizzo del server) e un numero di porta (per individuare il processo sulla macchina server).

Una applicazione server ascolta su una porta predefinita mentre attende una connessione. I clients selezionano il numero di porta corrispondente al servizio desiderato.

I numeri di porta sono codificati nelle RFC (Es. Telnet 23, FTP 21, ecc.), ma possono anche essere scelti (quasi) arbitrariamente per applicazioni custom.

Page 7: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J07

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Client port

Il numero di porta del client e’ tipicamente assegnato dal sistema operativo: la scelta di tale numero non e’ di solito rilevante.

Quando una client socket mand un pacchetto a una server socket, il pacchetto include la specifica della porta e dell’indirizzo del cliente: cosi’ il server e’ in grado di rispondere.

Page 8: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J08

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Sockets

Usando le sockets, si deve decidere che tipo di protocollo si desidera per il trasporto di pacchetti sulla rete:

Un protocollo connection-oriented oUn protocollo connectionless.

Page 9: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J09

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Connection-oriented protocols

Un protocollo connection-oriented offre l’equivalente di una conversazione telefonica.

•Dopo aver stabilito la connessione, due applicazioni possono scambiarsi dati.•La connessione rimane in essere anche se nessuno parla.

Il protocollo garantisce che non vengano persi dati e che questi arrivino sempre nell’ordine corretto.

La classe Java Socket usa un protocollo connection-oriented, e “parla” TCP

Page 10: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J010

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Connectionless Protocols

Un protocollo connectionless somiglia al servizio postale. Le applicazioni possono inviarsi brevi messaggi, ma non viene tenuta aperta una connessione tra un messaggio e l’altro.

Il protocollo NON garantisce che non vadano persi dati e che ne’ che questi arrivino nell’ordine corretto.

La classe DatagramSocket usa un protocollo connectionless, e “parla” UDP

Page 11: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J011

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Connection oriented Protocols

Con un connection-oriented protocol, una client socket stabilisce, alla sua creazione, una connessione con una server socket. Stabilita la connessione, un protocollo connection-oriented assicura la consegna affidabile dei dati, ovvero:

1. Ogni pacchetto spedito, il pacchetto viene consegnato. Ad ogni spedizione, la socket si aspetta di ricevere un acknowledgement cheil pacchetto e’ stato ricevuto con sucesso. Se la socket non riceve l’acknowledgement entro un tempo prestabilito, la socket ri-invia il pacchetto. La socket continua a provare finche’ la trasmissione ha successo, o finche’ decide che la consegna e’ impossibile.

Page 12: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J012

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Connection oriented Protocols

2. I paccheti sono letti from dalla socket ricevente nello stesso ordine in cui sono stati spediti. Per il modo in cui la rete funziona, i pacchetti possono arrivare alla socket destinataria in un ordine diverso da quello in cui sono stati spediti.

Un protocollo reliable, connection-oriented permette alla socket ricevente di riordinare i paccheti ricevuti, cosi’ che possano essere letti dal programma ricevente nell’orine in cui erano stati spediti.

Page 13: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J013

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

java.net.Socket

Questa classe implementa una socket per interprocess communication over the network.

I constructor methods creano la socket e la connettono allo host e porta specificati.

Page 14: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J014

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

java.net.Socket

Una volta creata la socket, getInputStream() e getOutputStream() ritornano oggetti InputStream e OutputStream che possono essere usati come se fossero canali di I/O su file.

getInetAddress() e getPort() restituicono indirizzo e porta a cui la socket e’ connessa.

getLocalPort() ritorna la porta locale usata dalla socket .

Page 15: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J015

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

java.net.ServerSocket

Questa classe e’ usata dai servers per ascoltare le richieste di connessione. Quando si crea una ServerSocket, si specifica su quale porta si ascolta.

Il metodo accept() iniza ad ascoltare su quella porta, e si blocca finche’ un client non richiede una connessione su quella porta.

A quel punto, accept() accetta la connessione, creando e ritornando una Socket che il server puo’ usare per comunicare col client.

Page 16: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J016

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Sockets

Clients

Un applicazione client apre una connessione con un server costruendo una Socket che

specifica hostname e port number del server desiderato:

try { Socket sock = new Socket(“www.pippo.it", 80); //Socket sock = new Socket("128.252.120.1", 80);

} catch ( UnknownHostException e ) { System.out.println("Can't find host.");

} catch ( IOException e ) { System.out.println("Error connecting to host.");

}

Page 17: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J017

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Connection-oriented protocol

Il lato server di un protocollo connection-oriented tipicamente esegue questa sequenza:

•Crea un ServerSocket object per accettare connessioni. •Quando il ServerSocket accetta la connection, crea un oggetto Socket che encapsula la connessione. •Alla Socket viene chiesto di creare oggetti InputStream e OutputStream che leggono e scrivono bytes da e verso la connessione. •La ServerSocket puo’ opzionalmente creare una nuova thread per ogni connessione, cosi’ che il server possa ascoltare per nuove connessioni mentre serve i clienti gia’ acquisiti.

Page 18: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J018

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Reading & Writing raw bytes – Client side

Una volta stabilita la connessione, input e output streams possono essere ottenuti con i metodigetInputStream() e getOutputStream() di Socket . try {

Socket server = new Socket("foo.bar.com", 1234); InputStream in = server.getInputStream();

OutputStream out = server.getOutputStream(); // Write a byte out.write(42); // Read a byte Byte back = in.read(); server.close();

} catch (IOException e ) { }

Page 19: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J019

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Reading & Writing newline delimited strings – Client

Incapsulando InputStream & OutputStream e’ possibile accedere agli streams in modo piu’ semplice.try {

Socket server = new Socket("foo.bar.com", 1234); InputStream in = server.getInputStream();

DataInputStream din = new DataInputStream( in );

OutputStream out = server.getOutputStream(); PrintStream pout = new PrintStream( out );

// Say "Hello" (send newline delimited string) pout.println("Hello!"); // Read a newline delimited string String response = din.readLine(); server.close();

} catch (IOException e ) { }

Page 20: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J020

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Reading & Writing raw bytes – Server side

try {

ServerSocket listener = new ServerSocket( 1234 ); while ( !finished ) {

Socket aClient = listener.accept(); // wait for connection InputStream in = aClient.getInputStream(); OutputStream out = aClient.getOutputStream(); // Read a byte Byte importantByte = in.read(); // Write a byte out.write(43); aClient.close();

} listener.close();

} catch (IOException e ) { }

Page 21: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J021

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Reading & Writing newline delimited strings – Server

try { ServerSocket listener = new ServerSocket( 1234 ); while ( !finished ) {

Socket aClient = listener.accept(); // wait for connection InputStream in = aClient.getInputStream(); DataInputStream din = new DataInputStream( in ); OutputStream out = aClient.getOutputStream(); PrintStream pout = new PrintStream( out ); // Read a string String request = din.readLine(); // Say "Goodbye" pout.println("Goodbye!"); aClient.close();

} listener.close();

} catch (IOException e ) { }

Page 22: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J022

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

This server is single-threaded

Questo server e’ single-threaded

Tratta una sola connessione alla volta; non chiama accept() per ascoltare nuove connessioni fin quando non ha finito con quella corrente.

Un server piu’ realistico avrebbe un loop che accetta connessioni e le passa ad altre thread per servirle concorrentemente.

Page 23: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J023

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

What about the Little Endian/Big Endian issue?

Le classi JavaDataInputStream and DataOutputStream

lavorano con i bytes di tipi interi in network byte order

(most significant to least significant).

Percio’ non c’e’ necessita’ di conversione dei dati!

Page 24: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J024

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Limitations

Applets e altre applicazioni che girano sotto il controllo del SecurityManager possono avere restrizioni arbitrarie su quali hosts possono raggiungere, e sul fatto di poter accettare connessioni. La security policy standard imposta dai browsers premette alle applets di aprire socket solo con lo host da cui provengono.Le applets are hanno il permesso di aprire server sockets.

Page 25: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J025

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Limitations

Ora, questo non significa che una applet non possa cooperare con il suo server per comunicare con chiunque e ovunque. Il server può girare un proxy che permette alla applet di comunicare indirettamente con chiunque.

Questo pone l’onere del controllo della sicurezza sul server originante, e non sulla macchina client.

Page 26: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J026

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP – Introduz.

TinyHttpd ascolta su una port specificata and serve semplici richieste HTTP "get file“:

GET /path/filename [optional stuff]

Il Web browser manda una o piu’ di queste linee per ogni documento da ottenere. Letta la richiesta, il server prova ad aprire il file specificato e ne spedisce il contenuto. Se il documento contiene referenze ad immagini o altro da mostrare online, il browser continua con richieste GET addizionali. Per ragioni di performance, TinyHttpd serve ogni richiesta in una sua thread. Percio’ TinyHttpd puo’ servire molte richieste concorrentemente.

Page 27: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J027

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP

import java.net.*; import java.io.*; import java.util.*;

public class TinyHttpd { public static void main( String argv[] ) throws IOException {

ServerSocket ss = new ServerSocket(Integer.parseInt(argv[0]));

while ( true ) new TinyHttpdConnection( ss.accept() );

} }

Page 28: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J028

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP

class TinyHttpdConnection extends Thread { Socket sock; TinyHttpdConnection ( Socket s ) {

sock = s; setPriority( NORM_PRIORITY - 1 ); start();

} public void run() { try { OutputStream out = sock.getOutputStream(); DataInputStream d=new DataInputStream(sock.getInputStream()); String req = d.readLine(); System.out.println( "Request: "+req ); StringTokenizer st = new StringTokenizer( req );

Page 29: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J029

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP

if ( (st.countTokens() >= 2) && st.nextToken().equals("GET") ) {

if ( (req = st.nextToken()).startsWith("/") ) req = req.substring( 1 );

if ( req.endsWith("/") || req.equals("") ) req = req + "index.html";

try { FileInputStream fis = new FileInputStream ( req ); byte [] data = new byte [ fis.available() ]; fis.read( data ); out.write( data );

} catch ( FileNotFoundException e ) new PrintStream( out ).println("404 Not Found"); }

else new PrintStream( out ).println( "400 Bad Request" ); sock.close(); } catch ( IOException e )

System.out.println( "I/O error " + e ); } }

Page 30: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J030

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP - uso

Compila TinyHttpd e mettilo nel tuo class path. Vai in una directory con qualche documento interessante e avvia il daemon, specificando un numero di porta non usato come argomento. Per esempio:

% java TinyHttpd 1234

Ora dovrebbe essere possibile usare un Web browser standard per ottenere i files dal tuo host. Nella URL dovra’ essere specificato il numero di porta scelto. Per esempio, se il tuo hostname e’ venezia.sodalia.it, ed hai avviato il server come sopra, sara’ possibile ottenere il file welcome.html con: http://venezia.sodalia,it:1234/welcome.html

Page 31: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J031

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP - Note

Abbassando la sua priorita’ a NORM_PRIORITY-1, assicuriamo che la threads che serve le

connessioni gia’ stabilite non blocchi la main thread di TinyHttpd impedendole di accettare

nuove richieste.

Page 32: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J032

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP - Problemi

TinyHttpd ha un sacco di possibilita’ di

miglioramento! Primo: consuma un sacco di memoria allocando un array enorme per leggere un intero the file

tutto d’un colpo. Un’implementazione piu’ realistica userebbe un buffer ed invierebbe i

dati in piu’ passei.

TinyHttpd inoltre non riconosce semplici directories. Non sarebbe difficile aggiungere

alcune lineee per leggere directories e generare liste di link HTML come fanno molti

web server.

Page 33: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J033

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP - Problemi

TinyHttpd soffre di limitazioni imposte dalla debolezza di accesso al filesystem.

E’ importante ricordare che le pathnames sono architecture dependent—cosi’ come il concetto stesso di filesystem. TinyHttpd funziona, cosi’ com’e’, su systemi UNIX e DOS-like, ma richiede alcune variazioni su altre piattaforme. E’ possibile scrivere del codice piu’ elaborato code che usa environmental information offerte da Java per adattarsi al sistema locale.

Page 34: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J034

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

Un mini-server concorrente HTTP - Problemi

Il problema principale con TinyHttpd e’ che non ci sono restrizioni sui files a cui puo’ accedere. Con qualche trucco, il daemon spedirebbe un

qualunque file del suo filesystem al client.

Sarebbe utile rlimitare TinyHttpd ai files che sono nella directory corrente, or una sua

subdirectory.

Page 35: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J035

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

mini-server concorrente HTTP – Security Manager

import java.io.*;

class TinyHttpdSecurityManager extends SecurityManager { public void checkAccess(Thread g) { }; public void checkListen(int port) { }; public void checkLink(String lib) { }; public void checkPropertyAccess(String key) { }; public void checkAccept(String host, int port) { }; public void checkWrite(FileDescriptor fd) { }; public void checkRead(FileDescriptor fd) { }; public void checkRead( String s ) {

if ( new File(s).isAbsolute() || (s.indexOf("..") != -1) )

throw new SecurityException("Access to file : "+s+" denied.");

} }

Page 36: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J036

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

mini-server concorrente HTTP – Security Manager

Il cuore di questo security manager e’ il metodo checkRead().

Controlla due cose: assicura che il pathname non sia assoluto, e che il pathname non contenga un double dot (..) che risale l’albero delle directories.

Con questi vincoli siamo certi (almeno su un filesystem UNIX o DOS-like) di aver ristretto l’accesso alle solo subdirectories della directory corrente. Se il pathname e’ absolute o contiene "..", checkRead() lancia una SecurityException.

Page 37: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J037

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

mini-server concorrente HTTP – Security Manager

Gli altri metodi che non fanno nulla --e.g., checkAccess()—permettono al daemon di fare il suo lavoro senza interferenza da paret del security manager.

Quando installiamo un security manager, ereditiamo implementazioni di molte "check" routines. L’implementazione default non permette di fare nulla; Lancia una security exception appena chiamata. Dobbiamo aprire dei buchi cosicche’ il daemon possa fare il suo lavoro; deve accettare connections, ascoltare sockets, creare threads, leggere property lists, ecc. Per questo sovrascriviamo i metodi default.

Page 38: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J038

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

mini-server concorrente HTTP – Security Manager

Per installare il security manager, aggiungere la seguente riga all’inizio del main di TinyHttpd:System.setSecurityManager( new TinyHttpdSecurityManager() );

Per catturare le security exception, aggiungere il seguente catch dopo la catch di FileNotFoundException': catch ( SecurityException e )

new PrintStream( out ).println( "403 Forbidden" );

Page 39: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J039

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

A simple e-mail client

import java.net.*;import java.io.*;import java.util.*;

class EMailClient{ public static void main(String[] args){

new EmailClient() } // end main EMailClient() { String server = "put your email server name here"; int port = 25; //mail port try{ //Get a socket, connected to the specified server // on the specified port. Socket socket = new Socket(server,port);

Page 40: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J040

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

A simple e-mail client

//Get an input stream from the socket BufferedReader inputStream = new BufferedReader(new InputStreamReader( socket.getInputStream())); //Get an output stream to the socket. Note // that this stream will autoflush. PrintWriter outputStream = new PrintWriter(new OutputStreamWriter( socket.getOutputStream()),true); //Begin the conversation with the email server. outputStream.println( "mail from: put your email name here"); System.out.println(inputStream.readLine()); outputStream.println( "rcpt to: " + "put your email name here"); System.out.println(inputStream.readLine()); outputStream.println("data"); System.out.println(inputStream.readLine());

Page 41: J0 1 Marco Ronchetti - ronchet@altavista.it Java Networking TCP.

J041

Marc

o R

onch

ett

i

-

ronch

et@

alt

avis

ta.it

A simple e-mail client

String timeStamp = (new Date()).toString(); outputStream.println("Test message " + timeStamp); outputStream.println("."); System.out.println(inputStream.readLine());//Close the socket socket.close(); }//end try catch(UnknownHostException e){ System.out.println(e); System.out.println( "Must be online to run properly."); }//end catch UnknownHostException catch(IOException e){System.out.println(e);} }//end constructor}//end class