Networking
URLs e URLConnections
Costruttori classe java.net.URL:
public URL(String urlName) throws MalformedURLExceptionoppure
public URL(URL context, String relativeName) throws MalformedURLExceptionNota che questi costruttori possono lanciare l'eccezione di tipo java.net.MalformedURLException , se la stringa passata nel costruttore non rappresenta un'url legale (come formato). MalformedURLException è sottoclasse di IOException e richiede il codice di gestione delle eccezioni obbligatorio.
Una volta avuto un oggetto di tipo URL, puoi chiamare il metodo openConnection() per aprire una connessione. Questo metodo restituisce un oggetto di tipo URLConnection. L'URLConnection a sua volta può essere usata per creare un InputStream per leggere dati dalla risorsa rappresentata dall'URL. Questo può essere fatto invocando il metodo getInputStream(). Per esempio:
URL url = new URL(urlAddressString);
URLConnection connection = url.openConnection();
InputStream in = connection.getInputStream(); I metodi openConnection() e getInputStream() possono entrambi generare IOException. Una volta che l'InputStream è creato, si può leggeer da esso nel modo usuale, incluso wrapparlo in un altro input stream, come BufferedReader o Scanner. Le letture dallo stream possono, naturalmente, generare delle eccezioni.
Un altro metodo d'istanza utile di URLConnection è getContentType(), che ritorna una String che descrive il tipo di informazione associata all'URL. Il valore di ritorno può essere null se il tipo dell'informazione non è conosciuto o se non è possibile determinare il tipo. L'informazione sul tipo potrebbe essere non disponibile finché l'input stream non sia creato, così in genere dovrebbe essere chiamato getContentType() dopo getInputStream(). La stringa ritornata da getContentType() è nel formato chiamato mime type. Mime types includono "text/plain", "text/html", "image/jpeg", "image/png" e molte altre. Tutti i mime type, contengono due parti: una parte generale come "text" o "image" e un tipo più specifico all'interno della categoria generale, come "html" o "png". Se ad esempio fossimo interessati solo a dati di tipo testo, si potrebbe controllare che la stringa ritornata da getContentType() inizi con "text". I Mime type furono all'inizio utilizzati per descrivere il contenuto dei messaggi di posta elettronica (email). Il nome sta per "Multipurpouse Internet Email Extensions". Essi sono usati oramai in modo universale per specificare il tipo di informazione di un file o altre risorse.
Sotto un piccolo esempio che sfrutta tutto questo per leggere i dati da un URL. La funzione sotto, apre una connessione all'URL specificata, controllo che il tipo di dato specificato nell'URl sia di tipo testo, e allora visualizza il dato a console.
/**
* This subroutine attempts to copy text from the specified URL onto the screen.
* Any error must be handled by the caller of this subroutine.
* @param urlString contains the URL in text form
*/
static void readTextFromURL( String urlString ) throws IOException {
/* Open a connection to the URL, and get an input stream
for reading data from the URL. */
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
InputStream urlData = connection.getInputStream();
/* Check that the content is some type of text. Note: If
getContentType() method were called before getting the input
stream, it is possible for contentType to be null only because
no connection can be made. The getInputStream() method will
throw an error if no connection can be made. */
String contentType = connection.getContentType();
System.out.println("Stream opened with content type: " + contentType);
System.out.println();
if (contentType == null || contentType.startsWith("text") == false)
throw new IOException("URL does not seem to refer to a text file.");
System.out.println("Fetching context from " + urlString + " ...");
System.out.println();
/* Copy lines of text from the input stream to the screen, until
end-of-file is encountered (or an error occurs). */
BufferedReader in; // For reading from the connection's input stream.
in = new BufferedReader( new InputStreamReader(urlData) );
while (true) {
String line = in.readLine();
if (line == null)
break;
System.out.println(line);
}
in.close();
} // end readTextFromURL()L'esempio completo del programma è: FetchURL.java
Socket (TCP)
L’astrazione principale per la programmazione di rete è il Socket:
Identifica le risorse che permettono di stabilire un canale di comunicazione con un altro processo (eventualmente su un’altra macchina).
Tutto quello che viene trasmesso sono pacchetti TCP.
I partecipanti di una comunicazione tramite socket sono individuati da:
indirizzo IP.
numero di porta.
In Java si usa il package
java.netclassi:
Socket,ServerSocket
Comunicazione client-server
il
java.net.ServerSocketdel server si mette in attesa di una connessione;il socket del client si collega al server socket;
viene creato un socket sul server e quindi stabilito un canale di comunicazione con il client;
Mettersi in attesa di una connessione (lato Server)
Creare un’istanza della classe
java.net.ServerSocketspecificando il numero di porta su cui rimanere in ascolto.ServerSocket serverSocket = new ServerSocket(4567);
Chiamare il metodo
accept()che fa in modo che il server rimanga in ascolto di una richiesta di connessione (la porta non deve essere già in uso)Socket socket = serverSocket.accept();
Quando il metodo completa la sua esecuzione la connessione col client è stabilita e viene restituita un’istanza di
java.net.Socketconnessa al client remoto;
Aprire una connessione (lato Client)
Aprire un socket specificando indirizzo IP e numero di porta del server:
Socket socket = new Socket(“127.0.0.1”, 4567)All’indirizzo e numero di porta specificati ci deve essere in ascolto un processo server. Se la connessione ha successo si usano (sia dal lato client che dal lato server) gli stream associati al socket per permettere la comunicazione tra client e server (e viceversa) :
NB: per fare test in locale si può utilizzare l’indirizzo (riservato) di localhost, 127.0.0.1, che corrisponde al computer locale stesso.
Esempio Server: EchoServer
Si crei un server che accetta connessioni TCP sulla porta 1337.
Una volta accettata la connessione il server leggerà ciò che viene scritto una riga alla volta e ripeterà nella stessa connessione ciò che è stato scritto.
Se il server riceve una riga “quit” chiuderà la connessione e terminerà la sua esecuzione.
Codice Server: io.checksound.networking.EchoServer
Esempio Client: EchoClient
Si crei un client che si colleghi, utilizzando il protocollo TCP, alla porta 1337 dell’indirizzo IP 127.0.0.1.
Una volta stabilita la connessione il client legge, una riga alla volta, dallo standard input e invia il testo digitato al server.
Il client inoltre stampa sullo standard output le risposte ottenute dal server.
Il client deve terminare quando il server chiude la connessione.
Codice client: io.checksound.networking.LineClient
Codice completo
NOTA BENE: La versione del codice del server non può gestire più client che si connettono contemporaneamente essendoci un solo flusso di esecuzione, quello del main thread, che risulta impegnato nella comunicazione con il primo client che si connette e finché quest'ultimo rimane connesso non può accettare connessioni da altri client. Quando il primo client si sconnette, solo allora, il server può accettare la connessione del secondo client che aveva tentato di connettersi ed era rimasto in attesa. E così via con i client che si connettono in seguito; UN SOLO CLIENT VIENE SERVITO ALLA VOLTA.
Impareremo con il capitolo 'I Thread e networking' come Java implementa la gestione di più client che si connettono contemporaneamente a un server: la soluzione è tramite l'utilizzo dei thread, meccanismo che permette di avere più flussi di esecuzione all'interno della stesso programma. I thread sono l'argomento del prossimo capitolo. Un po' di pazienza quindi.
UN SEMPLICE DATE SERVER
Il server accetta le connessioni dai client e invia la data corrente sull'output stream.
Il codice del client che fa la richiesta e riceve la data sotto forma di stringa sull'output di input:
UNA SEMPLICE APPLICAZIONE CHAT DI TIPO CLIENT/SERVER
Codice di un server che assieme a un client offre un servizio di chat.
Questo programma è un po' più robusto del DateServer. Prima di tutto utilizza un handshake (stretta di mano, letteralmente) per essere sicuro che il client che sta cercando di connettersi è realmente un programma CLChatClient. Un handshake è una semplice informazione invita tra il client e il server come parte del settaggio della connessione, prima che i dati vengano inviati. In questo caso, ogni lato della connessione, invia una stringa all'altro lato per identificare se stessa. L'handshake fa parte del protocollo che si è convenuto tra CLChatClient e CLChatServer. Un protocollo è una specifica dettagliata di quali dati e messaggi possono essere scambiati su una connessione e in quale ordine. Quando si implementa un'applicazione di tipo client/server, i design del protocollo è una problematica importante. Un altro aspetto del CLChat protocol, è che dopo l'handshake, ogni linea di testo che è inviata sulla connessione inizia con una carattere che agisce come comando. Se il carattere è 0, il resto della stringa è il messaggio da un utente all'altro. Se il carattere è 1, la stringa indica che l'utente ha digitato il comando "quit", è deve essere eseguito lo shut down della connessone.
Il codice del client:
RIASSUNTO
Gli esempi qui visti hanno il limite che i server possono servire un solo client alla volta. Per creare dei server che possano servire più client contemporaneamente, abbiamo bisogno di server multithread; impareremo in seguito cosa sono i thread e come utilizzarli per creare dei server che possano rispondere a più client contemporaneamente.
Esempi Networking
RISORSE
Per Networking http://math.hws.edu/eck/cs124/javanotes7/c11/s4.html
Last updated