Programmazione di rete in Java Java fornisce per la gestione della comunicazione le classi del package di networking java.net Gerarchia delle classi in Java Package java.net le socket rappresentano il terminale (end point) di un canale di comunicazione bidirezionale Un Client e un Server su macchine diverse possono comunicare sfruttando due diversi tipi di modalità di comunicazione • con connessione, in cui viene stabilita una connessione tra Client e Server (esempio, il sistema telefonico) Uso di socket STREAM • senza connessione, in cui non c’è connessione e i messaggi vengono recapitati uno indipendente-mente dall’altro (esempio, il sistema postale) Uso di socket DATAGRAM classi per SOCKET INTERNET • con connessione • classe Socket, per socket lato Client, con connessione (TCP) • classe ServerSocket, per socket lato Server, con connessione (TCP) • senza connessione • classe DatagramSocket, per socket (C/S) senza connessione (UDP) C/S in Java: Socket in Java - 1 Le classi sono state significativamente estese dalla diverse versioni delle JVM per tenere conto delle diverse necessità applicative C/S in Java: Socket in Java - 2 Sistema di NOMI NOMI per SOCKET Necessità di definire un sistema identificazione delle entità messe in gioco Una macchina è identificata univocamente da un indirizzo IP (4 byte / 32 bit) (livello IP) La porta è un numero intero di 16 bit (astrazione fornita dal TCP e da UDP) di Un’applicazione distribuita è costituita da processi distinti per località che comunicano e cooperano attraverso lo scambio di messaggi, per ottenere risultati coordinati Il primo problema da affrontare riguarda la identificazione dei processi (il Client o il Server) nella rete Per ogni processo bisogna definire un NOME GLOBALE visibile in modo univoco e sempre non ambiguo “nome” della macchina + “nome” del processo all’interno della macchina Gli endpoint di processo (socket) sono tipicamente locali al processo stesso (livello applicativo o sottostante fino a sessione) Il problema è risolto dai livelli sottostanti di protocollo per le socket nel dominio Internet i nomi di trasporto (TCP, UDP) e rete (IP) C/S in Java: Socket in Java - 3 NOME GLOBALE I messaggi sono consegnati su una specifica porta di una specifica macchina, non direttamente a un processo NOME LOCALE Un processo si lega a una porta per ricevere (o spedire) dei messaggi o anche più processi si collegano In questo modo è possibile identificare un processo senza dover conoscere il suo process identifier (pid) Un indirizzo IP e una porta possono rappresentare un endpoint di un canale di comunicazione NOME IP NUMERO PORTA livello network - OSI 3 livello trasporto - OSI 4 C/S in Java: Socket in Java - 4 Caso di Server sequenziale o iterativo NOMI GLOBALI Numeri IP => vedi protocollo IP indirizzo IP: ad es. 137.204.57.186 Numeri di Porta porte 4 cifre hex: XXXXh spesso espresse con unico decimale una richiesta alla volta (con connessione o meno) I tempi di risposta al servizio aumentano ==> servizi brevi server sequenziale senza connessione servizi senza stato (che introduce ritardi) e non soggetti a guasti ad es. 153, 2054 unica coda C1 Funzione fondamentale delle porte è identificare un servizio risposta sulla porta cliente Cn I numeri di porta minori di 1024 sono riservati (well-known ports, o reserved) sono standardizzati i servizi offerti dai processi che a tale porta sono legati Per esempio, il servizio Web è identificato dalla porta numero 80, cioè il processo server di un sito Web deve essere legato alla porta 80, su cui riceve i messaggi con le richieste di pagine html Altri esempi: porta 21 per ftp, porta 23 per telnet, porta 25 per mail,… #portaserver #portac1 unica coda iniziale risposta sulla C/S in Java: Socket in Java - 5 della Processo Server Controllore porta cliente #portaserver Cn Azioni unica connessione stabilita C1 La richiesta di un servizio a un processo server non richiede quindi la conoscenza del suo pid, ma solo della porta e IP (nomi globali) Azioni server sequenziale con connessione servizi con requisiti di reliability limitando lo stato (uso di TCP) difficile realizzazione pratica overhead delle azioni di controllo connessione C1 Processo Server Controllore #portac1 #portaserver C/S in Java: Socket in Java - 6 SERVER concorrente singolo processo non parallelo Server concorrente più richieste alla volta (multi o singolo processo) SERVER PARALLELO processi multipli uso di processi multipli, un master server generazione di processi interni per ogni servizio massimo parallelismo per servizi non interferenti Si deve garantire che il costo di generazione del processo non ecceda il guadagno ottenuto in caso di connessione e stato (limitati) realizzato con un unico processo che produce effetti di concorrenza dal punto di vista dei clienti l'unico processo master deve considerare tutte le richieste ed servirle al meglio (mantenendo le connessioni) Facciamo il caso di connessione (ma anche senza) Soluzione con processi creati in precedenza che consentano di essere velocemente smistati al servizio necessario numero prefissato di processi iniziali e altri creati su necessità e mantenuti per un certo intervallo Server parallelo senza connessione #porta1 C1 richieste iniziali Cn C1 Processo Server Controllore #portaserver #portan connessione #porta1 Azioni C1 Processo Server Controllore Cn #portaserver Ci #portan generazione processo connessione Porte differenziate C1 Processo Server Controllore Cn #porta1 Azioni Ci Unico Processo Server Processi Client attivi #portan Necessità di rispondere in modo veloce alle richieste successive e sollecitazioni Cn Processi Client attivi Processi Server Un canale unico e un processo per ogni servizio C/S in Java: Socket in Java - 7 (REALIZZABILE IN JAVA???) C/S in Java: Socket in Java - 8 SOCKET per DATAGRAM SOCKET DATAGRAM Le socket DATAGRAM permettono a due thread di scambiarsi messaggi senza stabilire una connessione tra i thread convolti Necessità di protocollo Scambio di messaggi da socket datagram meccanismo di comunicazione non è affidabile possibili perdite di messaggi (per problemi di rete) consegna non in ordine a causa del protocollo UDP Vi è un solo tipo di socket DATAGRAM sia per il Client sia per il Server La classe java.net.DatagramSocket public final class DatagramSocket extends Object Costruttore (ce ne sono altri) DatagramSocket( InetAddress localAddress, int localPort) throws... il costruttore DatagramSocket crea socket UDP e fa un binding locale a porta e nome IP SCAMBIO MESSAGGI usando send e receive sock.send(DatagramPacket); sock.receive(DatagramPacket); Si usano sempre classi accessorie di supporto C/S in Java: Socket in Java - 9 Socket invio Socket Socket Porta1 Nome IP invio Socket ricezione Socket Socket Porta2 Nome IP ric. Le due socket messe in gioco devono essere state x inizializzate correttamente (create) x devono conoscersi In particolare chi invia: il mittente deve specificare nel messaggio che vuole comunicare con un ricevente (e una sua socket) Si devono specificare informazioni di tipo applicativo parte dati il messaggio (o lo spazio per il messaggio) di controllo comunicazione parte controllo il nodo del ricevente, la porta per arrivare alla socket del ricevente Nessuna garanzia nelle operazioni a causa del protocollo di supporto (UDP e IP) C/S in Java: Socket in Java - 10 Classi Accessorie Parte Dati Dati utente DatagramPacket Classe introdotta per usare e preparare datagrammi che consentono di specificare cosa comunicare (parte dati) come comunicare e con chi (parte controllo) Una istanza datagramma specifica un array di byte da/su cui scrivere e con indicazioni di comunicazione con diversi costruttori Parte controllo Interi per la porta e InetAddress InetAddress classe per gli indirizzi IP ad esempio public static InetAddress getByName (String hostname); solo alcuni metodi pubblici statici (public static): getByName(String hostname); fornisce un oggetto InetAddress per l’host specificato (null default locale) InetAddress[ ] getAllByName(String hostname); fornisce un array di oggetti InetAddress per più indirizzi IP sullo stesso nome logico InetAddress getLocalHost(); fornisce InetAddress per macchina locale C/S in Java: Socket in Java - 11 Tramite un Contenitore unificato DatagramPacket( byte [] buf, // array di byte dati int offset, // indirizzo inizio int length, // lunghezza dati InetAddress address, // indirizzo IP int port); // porta che prevede anche molti altri costruttori e molte funzioni di utilità come getAddress(), setAddress(InetAddress addr) getPort(), setPort(int port) getData(), setData(byte[] buf), … Nel DatagramPacket si deve considerare l’uso a secondo della funzione che stiamo invocando: x in invio dobbiamo avere una area su cui l’utente possa mettere i dati e l'area per accogliere le informazioni di controllo sul ricevente (fornite dal mittente del pacchetto). x in ricezione dobbiamo avere preparato tutto per ricevere tutte le informazioni, sia per la parte dati, sia per la parte di controllo (indirizzo del mittente) C/S in Java: Socket in Java - 12 Socket Multicast Schema di comunicazione Creazione socket Sono anche possibili ulteriori classi per inviare messaggi multicast e gruppi di multicast DatagramSocket socket = new DatagramSocket(); Preparazione gruppo: IP classe D e porta libera Preparazione informazione da inviare e invio byte[] buf = {'C','i','a','o'}; InetAddress addr = InetAddress. getByName("137.204.59.72"); int port = 1900; DatagramPacket packet = new DatagramPacket (buf, buf.length, addr, port); socket.send(packet); Preparazione, attesa informazione, e ricezione int report; InetAddress recaddress; byte [] result = new byte [200]; socket.receive(packet); recport = packet.getPort(); recaddress = packet.getAddress(); result = packet.getData(); InetAddress gruppo = InetAddress. getByName("229.5.6.7"); MulticastSocket s = new MulticastSocket(6666); Operazioni di ingresso/uscita dal gruppo // unisciti al gruppo ... s.joinGroup(gruppo); byte[] msg = {'H', 'e', 'l', 'l', 'o'}; DatagramPacket packet = new DatagramPacket (msg, msg.length, gruppo, 6666); s.send(packet); // ottenere i messaggi inviati byte[] buf = new byte[1000]; DatagramPacket recv = new DatagramPacket (buf, buf.length); s.receive(recv); ... // uso delle informazioni C/S in Java: Socket in Java - 13 // esci dal gruppo ... s.leaveGroup(group); C/S in Java: Socket in Java - 14 SOCKET per STREAM SOCKET per STREAM Le socket STREAM sono i terminali di un canale di comunicazione virtuale creato prima di comunicare tra il Client e il Server La comunicazione avviene in modo bidirezionale, affidabile, con dati (byte) consegnati in sequenza una sola volta (modalità FIFO come sulle pipe di Unix) e se non consegnati??? semantica at-most once La connessione tra i processi Client e Server è definita non dai processi che devono comunicare ma da una quadrupla univoca <protocollo; indirizzo IP Client; porta Client; indirizzo IP Server; porta Server> Nel caso delle socket STREAM, il protocollo di comunicazione sottostante è il protocollo TCP (+ IP) • TCP è un protocollo di trasporto, livello 4 OSI e fornisce l’astrazione porta • IP è un protocollo di rete, livello 3 OSI e identifica univocamente ogni macchina collegata alla rete Internet La comunicazione tra Client e Server su stream segue uno schema asimmetrico e il principio della connessione (relative API diverse) Questa considerazione ha portato al progetto di due tipi di socket diverse una per il Client e una per il Server C/S in Java: Socket in Java - 15 Protocollo di Comunicazione con Connessione in Java Richiesta di connessione Client Application Socket Socket Server Server Socket Socket Server Application Client Application Socket Socket Socket Socket Socket Socket Classi distinte per ruoli Cliente e Servitore La classe java.net.Socket La classe java.net.ServerSocket I costruttori delle classi tendono a nascondere i dettagli realizzativi I costruttori creano la socket, la legano a una porta locale e la connettono a una porta della macchina remota (Unix API più complesse e complete: vedi socket, bind, connect) C/S in Java: Socket in Java - 16 Lato CLIENTE Operazioni CLIENTE - costruttori La classe Socket consente di creare una socket con connessione, stream (TCP) per il collegamento di un Client a un Server socket è detta anche socket “attiva” public Socket(InetAddress remoteHost, int remotePort) throws IOException; Crea una socket stream cliente e la collega alla porta specificata della macchina all’indirizzo IP dato (equivale in Unix a: socket, bind, connect) I costruttori della classe creano la socket, la legano a una porta locale e ... la connettono a una porta di una macchina remota su cui sta il server La connessione permette poi comunicazione bidirezionale (full duplex) Server Server Socket Socket una Server Application Client Socket Socket Socket Porta Socket Nome IP Si noti che la creazione della socket produce in modo atomico anche la connessione al server corrispondente (deve essere presente) (Unix API più complesse e complete: vedi socket, bind, connect) C/S in Java: Socket in Java - 17 public Socket(String remoteHost, int remotePort) throws IOException; Crea una socket stream cliente e la collega alla porta specificata della macchina di nome logico remoteHost public Socket(InetAddress remoteHost, int remotePort, InetAddress localHost, int localPort) throws IOException; Crea una socket stream cliente e la collega sia a una porta della macchina locale (se localPort vale zero, il numero di porta è scelto automaticamente dal sistema) sia a una porta della macchina remota (macchine multihomed) La creazione della socket produce in modo atomico anche la connessione al server corrispondente o lancia la eccezione opportuna C/S in Java: Socket in Java - 18 Connessioni Operazioni CLIENTE - supporto la creazione di una socket a stream se va a buon fine produce una connessione bidirezionale a byte (stream) tra i due processi interagenti e impegna risorse sui nodi e tra i processi Per ottenere informazioni sulle socket si possono utilizzare i metodi aggiuntivi APERTURA ottenuta con il costruttore in modo implicito CHIUSURA operazione necessaria per non impegnare troppe risorse di sistema Le risorse diventano le connessioni: costa definirle e crearle, come distruggerle e mantenerle Si tendono a mantenere le sole connessioni necessarie Limiti alle aperture contemporanee di sessioni Il numero di connessioni che un processo (Client o Server) può aprire è limitato, => si chiudono le connessioni non utilizzate Il metodo close() chiude l’oggetto socket disconnette il Client dal Server public synchronized void close() C/S in Java: Socket in Java - 19 public InetAddress getInetAddress(); restituisce l’indirizzo della macchina remota a cui la socket è connessa public InetAddress getLocalAddress(); restituisce l’indirizzo della macchina locale public int getPort(); restituisce il numero di porta sulla macchina remota cui la socket è connessa public int getLocalPort(); restituisce il numero di porta sulla macchina locale a cui la socket è legata Esempio: int porta = oggettoSocket.getPort(); Client Socket Socket Socket e Porta Nome IP Socket Server sul Socket Server Porta Server Application Socket Nome IP C/S in Java: Socket in Java - 20 Uso di stream tipici di Java Esempio Operazioni di comunicazione su stream Client di echo (il Server Unix è sulla porta 7) Lettura o scrittura da/su una socket con i metodi: public InputStream getInputStream() ritorna l’input stream per leggere dei byte dalla socket public OutputStream getOutputStream() ritorna l’output stream per scrivere dei byte sulla socket try { oggSocket = new Socket(hostname, 7); /* input ed output sugli endpoint della connessione via socket */ out = new PrintWriter (oggSocket.getOutputStream(),true); in = new BufferedReader (new InputStreamReader (oggSocket.getIntputStream()); /* lettura da input */ userInput = new BufferedReader( new InputStreamReader(System.in)); I due metodi restituiscono un oggetto stream che incapsula il canale di comunicazione (di classi InputStream e OutputStream) . . . Attraverso gli stream si possono spedire/ricevere solo byte, senza nessuna formattazione naturalmente i byte arrivano ordinati non duplicati (non possono arrivare byte successivi, senza che arrivino i precedenti) i dati arrivano al più una volta at-most-once e in caso di errore? nessuna conoscenza while((oggLine = userInput.readLine()) != null) /* lettura input fino a fine file */ { out.println(oggLine); System.out.println(in.readLine()); } oggSocket.close(); } // fine try catch (IOException e) { System.err.println(e);} Altri oggetti possono incapsulare questi stream, per fornire funzionalità di più alto livello (es., DataInputStream) ... C/S in Java: Socket in Java - 21 C/S in Java: Socket in Java - 22 La classe java.net.ServerSocket Costruttori per il server Lato server public ServerSocket(int localPort) throws IOException, BindException; crea una socket in ascolto sulla porta specificata La classe ServerSocket definisce una socket capace di accettare richieste di connessione provenienti dai diversi Client più richieste di connessione pendenti allo stesso tempo e più connessioni aperte contemporaneamente Definisce anche la lunghezza della coda in cui vengono messe le richieste di connessione non ancora accettate dal server Una volta stabilita la connessione (ottenuta dal server tramite il metodo accept) la trasmissione dei dati avviene attraverso un normale oggetto Socket del server (restituito dalla accept) Al momento della creazione si effettuano implicitamente le operazioni più elementari visibili in UNIX, come socket, bind e listen public ServerSocket(int localPort, int count) throws IOException, BindException; crea una socket in ascolto sulla porta specificata con una coda di lunghezza count Le richieste accodate non sono servite automaticamente => necessità di un API che esprima la volontà di servizio Il server gioca un ruolo "passivo" deve specificare la coda delle possibili richieste ed aspettare i clienti comincia a decidere con la introduzione volontaria della primitiva di accettazione esplicita ACCEPT di una connessione C/S in Java: Socket in Java - 23 C/S in Java: Socket in Java - 24 ACCEPT di connessione Informazioni sulle socket connesse: Il Server si mette in attesa di nuove richieste di connessione chiamando il metodo accept() public InetAddress getInetAddress() restituisce l’indirizzo della macchina locale a cui la socket server è connessa public int getLocalPort() restituisce il numero di porta sulla macchina locale La invocazione di accept blocca il Server fino all’arrivo di una richiesta Quando arriva una richiesta, accept stabilisce una la reale connessione tra il Client e un nuovo oggetto Socket restituito da accept e che rappresenta lo stream con il cliente public Socket accept() throws IOException; La accept restituisce un oggetto della classe Socket su cui avviene la comunicazione tra Client e Server la chiamata di accept mette il servitore in attesa di richieste di connessione Tipicamente se non ci sono ulteriori richieste, il servitore si blocca in attesa Se c’è almeno una richiesta, si sblocca la primitiva e si crea la connessione per questa La trasmissione dei dati avviene con i metodi visti per il lato Client in modo del tutto indifferente in uno o l'altro verso della connessione i due endpoint sono del tutto omogenei (uso di protocollo TCP) C/S in Java: Socket in Java - 25 Server daytime (il Server Unix su porta 13) ... oggServer = new ServerSocket(portaDaytime); try { /* il server alla connessione invia la data al cliente */ while (true) { oggConnessione = oggServer.accept(); out = new PrintWriter (oggConnessione.getOutputStream(), true); Date now=new Date(); // produce la data out.write(now.toString()+ "\r\n"); oggConnessione.close(); } } catch (IOException e) { oggServer.close(); oggConnessione.close(); System.err.println(e); } . . . C/S in Java: Socket in Java - 26 Server Parallelo con connessione Esempio possible Remote CoPy (RCP) Richi es ta di conn ession e Thread Server (padre) Comunica zi one Client/ accept (); <attesa su ServerSocket> <generazione thread> <padre continua> Server < servizio della richiesta uso di Socket > Nuovo Thread Alla accettazione il servitore può generare una nuova attività responsabile del servizio (che eredita la connessione nuova) Il servitore principale può aspettare nuove richieste e servire nuove operazioni Si realizzi un’applicazione distribuita Client/Server per eseguire la copia remota (remote copy, rcp) di file Progettare sia il programma client sia il programma server Il programma Client deve consentire la invocazione: rcp_client nodoserver portaserver nomefile nomefiledest nodoserver e portaserver indicano il nome Server e nomefile è il nome di un file presente nel file system della macchina Client Il processo Client deve inviare il file nomefile al Server che lo scrive nel direttorio corrente con nome nomefiledest La scrittura del file nel direttorio specificato deve essere eseguita solo se in tale direttorio non è presente un file con lo stesso nome, evitando di sovrascriverlo Uso di connessione: il file richiede di trasferire anche grosse moli di dati e in ordine La connessione aperta dal cliente consente al server di coordinarsi per la richiesta del file che viene inviato !Versione non ottimizzata da migliorare! C/S in Java: Socket in Java - 27 C/S in Java: Socket in Java - 28 RCP Client RCP Server iterativo sequenziale Estratto del client ... ... rcpSocket = new Socket(host,porta); OutSocket = new DataOutputStream (rcpSocket.getOutputStream()); InSocket = new DataInputStream (rcpSocket.getInputStream()); OutSocket.writeUTF (NomeFileDest); Risposta = InSocket.readUTF(); System.out.println(Risposta); if (Risposta.equalsIgnoreCase ("MSGSrv: attendofile") == true) {FDaSpedDescr = new File(NomeFile); FDaSpedInStream = new FileInputStream(FDaSpedDescr); byte ContenutoFile [] = new byte [FDaSpedInStream.available()]; FDaSpedInStream.read(ContenutoFile); StrDatiOutSocket.write (ContenutoFile); }} // file letto tutto in un colpo? catch (IOException e) {System.err.println(e);} rcpSocket.close(); ... try { rcpSocketSrv = new ServerSocket(Porta); System.out.println("Attesa su porta" + rcpSocketServer.getLocalPort()); while(true) {SocketConn = rcpSocketSrv.accept(); System.out.println("con " + Socketconn); OutSocket = new DataOutputStream (SocketConn.getOutputStream()); InSocket = new DataInputStream (SocketConn.getInputStream()); NFile = InSocket.readUTF (); FileDaScrivere = new File(NFile); UTF formato standard Unified Transformation Format per maggiore portabilità C/S in Java: Socket in Java - 29 if(FileDaScrivere.exists() == true) { OutSocket.writeUTF( "MSGSrv: file presente, bye"); } else { OutSocket.writeUTF( "MSGSrv: attendofile"); byte ContntFile[] = new byte [1000]; InSocket.read(ContntFile); FileOutputStream = new FileOutputStream (FileDaScrivere); FileOutputStream.write(ContntFile); } SocketConn.close(); } // file letto tutto nel buffer ? } catch (IOException e) {System.err.println(e);} ... C/S in Java: Socket in Java - 30 RCP Server concorrente parallelo RCP Server Processi Figli ... try { ... rcpSocket = new ServerSocket(Porta); System.out.println("Attesa su porta" + rcpSocket.getLocalPort()); public class rcp_servizio extends Thread { ... rcp_servizio(Socket socketDaAccept) {rcpSocketSrv = socketDaAccept;} while(true) { rcpSocketConn = rcpSocket.accept(); threadServizio = new rcp_servizio (rcpSocketConn); threadServizio.start(); } } catch (IOException e) {System.err.println(e);} Si genera un nuovo processo per ogni connessione generata e su questa avviene la interazione Una socket usata è visibile da tutti i thread (condivisione risorse): la prima close chiude la socket definitivamente per tutti i thread Si noti che le socket usate dai thread sono tutte considerate impegnate per il sistema di supporto ???e se c'è un limite al numero di socket aperte per processo??? (e le porte?) C/S in Java: Socket in Java - 31 public void run() { System.out.println("thread numero " + Thread.currentThread()); System.out.println(""Connesso con" + + rcpSocketSrv); try {OutSocket= new DataOutputStream (rcpSocketSrv.getOutputStream()); InSocket = new DataInputStream (rcpSocketSrv.getInputStream()); NomeFile = InSocket.readUTF(); FileDaScrivere = new File(NomeFile); if(FileDaScrivere.exists () == true) /* in caso le cose siano terminate senza invio /* { OutSocket.writeUTF( "MSGSrv: file presente, bye"); } C/S in Java: Socket in Java - 32 /* solo in caso si consenta di trasmettere il file /* else /* scrittura effettiva del file */ { OutSocket.writeUTF( "MSGSrv: attendofile"); byte ContentFile [] = new byte [1000]; InSocket.read(ContentFile); FileDaScrivereOutputStream = new FileOutputStream (FileDaScrivere); FileDaScrivereOutputStream.write (ContentFile); } /* chiusura della connessione e terminazione del servitore specifico */ rcpSocketSrv.close(); System.out.println( "Fine servizio thread numero " + Thread.currentThread()); } catch (IOException e) { System.err.println(e); exit(1);} ... C/S in Java: Socket in Java - 33 Chiusura delle Socket Le socket in Java impegnano non solo il loro livello applicativo, ma anche una serie di risorse di sistema che sono collegate e necessarie per la operatività La chiusura è quindi necessaria sempre per dichiarare la non necessità di mantenere risorse non più in uso In casa di una socket chiusa, le risorse sono mantenute per un certo tempo (in dipendenza dalla importanza delle operazioni) In caso di socket connessa chiusa, la memoria viene mantenuta per continuare a spedire informazioni da inviare al pari Il pari si accorge di questo tramite: - eventi che gli vengono notificati in caso di operazioni (tipo lettura o scrittura sulla sua socket) - eccezioni o predicati Si vedano alcune funzioni come: isClosed (); isConnected (); isInputShutdown (); isOutputShutdown (); C/S in Java: Socket in Java - 34 Opzioni delle Socket URL Si esplorino le opzioni delle socket in Java con funzioni definite SetSoTimeout (int timeout) throws... la lettura da socket (es., read()) è bloccante. Questa opzione definisce un timeout (in msec), trascorso il quale si sblocca la read (ma viene lanciata una eccezione da gestire) timeout a zero, nessuna sospensione SetSendBufferSize (int size) throws... il buffer di invio dello stream può essere variato SetReceiveBufferSize (int size) il buffer di invio dello stream può essere variato SetReuseAdddress () si possono collegare più processi (e socket) ad un certo indirizzo fisico Solo socket a stream SetSoLinger (boolean on, int linger) dopo la close, il sistema tenta di consegnare i pacchetti ancora in attesa di spedizione. Questa opzione permette di scartare i pacchetti in attesa (linger in sec) SetTcpNoDelay (boolean on) throws ... il pacchetto è inviato immediatamente, senza bufferizzare SetKeepAlive (boolean on) throws... abilita, disabilita la opzione di keepalive Sono previste le get corrispondenti le opzioni sono disponibili nella classe SocketOptions C/S in Java: Socket in Java - 35 Inoltre visto l'ampio uso di Indirizzi Web La classe java.net.URL La classe URL descrive le risorse Internet http://deis.unibo.it/index.html protocol handler content handler metodo getContent Scaricamento di una pagina ... URL deis = new URL ("http://www.deis.unibo.it/"); BufferedReader in = new BufferedReader( new InputStreamReader( deis.openStream())); String inLine; while ((inLine = in.readLine())!=null) System.out.println(inLine); in.close(); ... possibilità di agganciarsi dinamicamente ad un URL e di gestire il trasferimento via protocollo HTTP C/S in Java: Socket in Java - 36