Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 1”
less
). I nomi dei file da mostrare sono passati come argomenti della linea di comando, ad esempio:java Less pippo.txt /usr/share/dict/words
final
oppure no.Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 2”
Scrivere un programma JAVA che attivi K thread, chiamati “T1”, “T2”, …, “TK”. Tutti i thread sono caratterizzati dallo stesso comportamento: ogni thread stampa i primi N numeri naturali, senza andare a capo (K e N sono dati in input dall'utente). Accanto ad ogni numero deve essere visualizzato il nome del thread che lo ha stampato, ad esempio usando il formato “: n [Tk] :”. Tra la stampa di un numero e quella del numero successivo ogni thread deve sospendersi per un intervallo di tempo la cui durata è scelta in modo casuale tra 0 e 1000 millisecondi.
Sviluppare due diverse versioni del programma che utilizzino le due tecniche per l'attivazione di threads presentate in questa lezione.
Scrivere un programma che avvia un thread che va in sleep per 10 secondi. Il programma principale interrompe il thread dopo 5 secondi. Il thread deve catturare l'eccezione e stampare il tempo (in millisecondi) trascorso in sleep.
Per ottenere l'ora corrente usare il metodo System.currentTimeMillis(), consultandone la documentazione on line.
Scrivere un programma che attiva un thread T che effettua il calcolo approssimato di pigreco. Il programma principale riceve in input da linea di comando due argomenti:
Il thread T effettua un ciclo infinito per il calcolo di pigreco usando la serie di Gregory-Leibniz (pigreco = 4/1 – 4/3 + 4/5 - 4/7 + 4/9 - 4/11 …).
Il thread esce dal ciclo quando una delle due condizioni seguenti risulta verificata:
Prima della terminazione il thread stampa il valore approssimato di pigreco calcolato fino a quel momento.
Modificare il programma dell'esercizio precedente in modo che il valore approssimato di pigreco calcolato dal thread venga stampato dal main.
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 3”
Scrivere un programma Java Resolve che traduca una sequenza di nomi simbolici di host nei corrispondenti indirizzi IP. Resolve legge i nomi simbolici da un file, il cui nome è passato da linea di comando oppure richiesto all'utente.
Scrivere un programma che enumeri e stampi a video tutte le interfacce di rete del computer, usando i metodi della classe java.net.NetworkInterface.
Scrivere un programma che ricerca una parola chiave (key) nei file contenuti in una directory (fornita dall'utente) e nelle sue sottodirectory. Per ogni file che contiene key, si deve visualizzare il nome dei file e il contenuto della prima riga trovata che contiene key.
<nome file> : <contenuto riga che contiene key>
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 4”
Si scriva un programma Java che dimostri che si possono verificare delle race conditions anche con una singola istruzione di incremento di una variabile.
Si consideri il metodo next() della classe Counter dell'Esercizio 1. Modificarlo in modo da renderne l'esecuzione non interrompibile, e rieseguire il programma controllando che non si verifichino più race conditions. Fare questo nei tre modi visti:
Il laboratorio di Informatica del Polo Marzotto è utilizzato da tre tipi di utenti, studenti, tesisti e professori ed ogni utente deve fare una richiesta al tutor per accedere al laboratorio. I computer del laboratorio sono numerati da 1 a 20. Le richieste di accesso sono diverse a seconda del tipo dell'utente:
I professori hanno priorità su tutti nell'accesso al laboratorio, i tesisti hanno priorità sugli studenti.
Scrivere un programma JAVA che simuli il comportamento degli utenti e del tutor. Il programma riceve in ingresso il numero di studenti, tesisti e professori che utilizzano il laboratorio ed attiva un thread per ogni utente. Ogni utente accede k volte al laboratorio, con k generato casualmente.
Simulare l'intervallo di tempo che intercorre tra un accesso ed il successivo e l'intervallo di permanenza in laboratorio mediante il metodo sleep. Il tutor deve coordinare gli accessi al laboratorio. Il programma deve terminare quando tutti gli utenti hanno completato i loro accessi al laboratorio.
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 5”
fujih2
, fujih3
, …, fujih40
. Per controllare se un host è sotto Linux e raggiungibile, eseguire da shell il comando ssh <nomeHost>
e fornire la password: questo aprirà una shell sul computer <nomeHost>
, con directory corrente la vostra home-directory.&
dopo il comando) e usare la shell per far partire altri processi. Scrivere un'applicazione composta da un processo Sender e un processo Receiver. Il Receiver riceve da linea di comando la porta su cui deve porsi in attesa. Il Sender riceve da linea di comando una stringa e l’indirizzo del Receiver (indirizzo IP + porta), e invia al Receiver la stringa. Il Receiver riceve la stringa e stampa, nell'ordine, la stringa ricevuta, l'indirizzo IP e la porta del mittente.
Considerare poi i seguenti punti:
Si richiede di programmare un server CountDownServer che fornisce un semplice servizio: ricevuto da un client un valore intero n, il server spedisce al client i valori n-1,n-2,…,1,0 in sequenza.
Il client deve calcolare il numero di pacchetti persi e quello di quelli ricevuti fuori ordine e lo visualizza alla fine della sessione. Utilizzare le classi ByteArrayOutput/InputStream per la generazione/ricezione dei pacchetti.
La interazione tra i clients e CountDownServer è di tipo connectionless. Si richiede di implementare due versioni di CountDownServer
Per testare il funzionamento del client, può essere utile usare la classe UnreliableDatagramSocket, che offre le stesse funzionalità di DatagramSocket
, ma perde il pacchetto da inviare con probabilità “threshold
”, una quantità compresa tra 0 e 1, modificabile con il metodo setThreshold(double)
e con valore default 0.1
.
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 6”
Scrivere la classe Obj2DP che fornisce due metodi statici:
public static Object dp2obj(DatagramPacket dp)
che restituisce l'oggetto contenuto nel pacchetto passato per argomento, deserializzandolo, e
public static DatagramPacket obj2dp(Object obj)
che restituisce un pacchetto contenente l'oggetto passato per argomento, serializzato, nel payload.
Semplificare le classi UDP_SendObject e UDP_ReceiveObject viste a lezione usando i metodi della classe Obj2DP, senza più usare le classi ObjectOutput/InputStream e ByteOutput/InputStream.
Usare la classe Obj2DP per i prossimi esercizi, trasmettendo oggetti serializzati con UDP invece di dati di tipi primitivi.
Si realizzino un Server e un Client UDP che realizzano un semplice Instant Messanger: ogni linea scritta nella shell del Server viene copiata nella shell del Client e viceversa. La trasmissione delle linee inizia dopo una semplice fase di handshaking, descritta di seguito.
Il Client e il Server devono scambiarsi unicamente oggetti della classe TalkMsg, usando i metodi della classe per crearne istanze e per ispezionare i messaggi arrivati.
Riusando il più possibile il codice sviluppato per l'esercizio precedente, realizzare un programma Messanger che offre le stesse funzionalità, ma in cui non si distinguono un Server e un Client.
Due istanze di Messanger devono essere lanciate in due shell diverse, fornendo ad ognuna tre dati: la porta locale, e l'host e la porta dell'altro Messanger. Ideare un opportuno protocollo di handshaking, che permetta di stabilire una connessione (concettuale) tra le due istanze di Messanger.
I messaggi scambiati devono essere tutti oggetti di una stessa classe. Usare la classe TalkMsg, oppure estenderla o definirne una analoga se necessario.
Questa è la specifica di TFTP da WIKIPEDIA:
Realizzare un Server TFTP che implementa il comportamento dell'host B e un Client TFTP che implementa l'host A. In particolare:
Per testare il programma:
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 7”
Progettare un'applicazione client/server in cui il server fornisca un servizio di compressione di dati. Il client legge chunks di bytes da un file e li spedisce al server che provvede alla loro compressione. Il server restituisce i bytes in formato compresso al client che provvede a creare un file con lo stesso nome del file originario e con estensione gz, che contiene i dati ricevuti dal server.
La comunicazione tra client e server utilizza il protocollo TCP. Per la compressione si può utilizzare la classe JAVA GZIPOutputStream.
Individuare le condizioni necessarie affinchè il programma scritto generi una situazione di deadlock e verificare che tale situazione si verifica realmente quando tali condizioni sono verificate.
Suggerimento: Scrivere il server in modo che riceva i byte e li rispedisca nello stesso loop. Scrivere una prima versione del client che prima invia tutto il file al server e solo alla fine riceve il file compresso dal server. Verificare che per file grandi questa soluzione va in deadlock, e scrivere in un commento perché. Scrivere una seconda versione del client che non abbia questo problema.
Considerare un servizio attivo su una porta pubblicata da un Server (per esempio, 23 Telnet, 25 SMTP, 80 HTTP). Definire un client JAVA che utilizzi tale servizio, dopo aver controllato che sia attivo.
Attenzione: Purtroppo ad un controllo più accurato risulta che tutti questi servizi (e anche altri suggeriti precedentemente) sono disattivati sui computer del Centro di Calcolo. Si consiglia di svolgere l'esercizio usando
come protocollo HTTP sulla porta 80, e come host un web server (per esempio, www.cli.di.unipi.it
).
Scrivere un semplice client HTTP in grado di effettuare una breve sequenza di richieste al server, stampando i risultati. Per testare il protocollo si può usare il comando telnet <webServer> 80
, che apre una connessione TCP
attraverso la quale si possono scambiare stringhe.
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 8”
Sviluppare un programma client server per il supporto di un'asta elettronica.
Ogni client possiede un budget massimo B da investire. Il client può richiedere al server il valore V della migliore offerta pervenuta fino ad un certo istante e decidere se abbandonare l'asta, oppure rilanciare. Se il valore ricevuto dal server supera B,l'utente abbandona l'asta, dopo aver avvertito il server. Altrimenti, il client rilancia, inviando al server un valore maggiore di V.
Il server invia ai client che lo richiedono il valore della migliore offerta ricevuta fino ad un certo momento e riceve dai client le richieste di rilancio. Per ogni richiesta di rilancio, il server notifica al client se tale offerta può essere accettata (nessuno ha offerto di più nel frattempo), oppure è rifiutata. Il server deve attivare un thread diverso per ogni client che intende partecipare all'asta.
La comunicazione tra clients e server deve avvenire mediante socket TCP. Sviluppare due diverse versioni del programma che utilizzino, rispettivamente una codifica testuale dei messaggi spediti tra client e server oppure la serializzazione offerta da JAVA in modo da scambiare oggetti tramite la connessione TCP
Definire un server TimeServer, che invia su un gruppo di multicast dategroup, ad intervalli regolari, la data e l’ora. L’attesa tra un invio ed il successivo può essere simulata mediante il metodo sleep( ). L’indirizzo IP di dategroup viene introdotta linea di comando.
Definire quindi un client TimeClient che si unisce a dategroup e riceve, per dieci volte consecutive, data ed ora, le visualizza, quindi termina.
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 9”
Sviluppare una applicazione RMI per la gestione di un’elezione. Il server esporta un insieme di metodi:
public void vota (String nome)
: Accetta come parametro il nome del candidato. Non restituisce alcun valore. Registra il voto di un candidato in una struttura dati opportunamente scelta.public int risultato (String nome)
: Accetta come parametro il nome di un candidato e restituisce i voti accumulati da tale candidato fino a quel momento.Il client invoca un certo numero di volte i metodi del server su opportuni argomenti (eventualmente forniti interattivamente dall'utente), stampando i risultati ottenuti. Testare che il sistema funzioni con server e client sullo stesso host e su host diversi. Nel secondo caso, provare due versioni: con il registry sull'host del server (come negli esempi visti), e con il registry sull'host del client.
Scrivere opportune classi e interfacce per verificare che nel caso di valori di tipo riferimento (oggetti e array), una invocazione di metodo remota passa al metodo chiamante una copia dell'oggetto passato come parametro, diversamente da quanto accade nel caso di una invocazione locale. Mostrare che invece, se il parametro è un oggetto remoto, allora viene passato un riferimento all'oggetto e non una sua copia.
Modificare l’Esercizio 1 dell'esercitazione precedente in modo che il server notifichi ogni nuovo voto ricevuto a tutti i clients che hanno votato fino a quel momento. La registrazione dei clients sul server avviene nel momento del voto.
Si vuole implementare un sistema che implementi un servizio per la gestione di forum in rete. Un forum è caratterizzato da un argomento su cui diversi utenti, iscritti al forum, possono scambiarsi opinioni via rete. Il sistema deve prevedere un server RMI che fornisca le seguenti funzionalità:
Quindi il messaggio può essere richiesto esplicitamente dal client oppure può essere notificato ad un client precedentemente registrato.
Si realizzi un programma Crawler che analizza tutti i file presenti in una directory specificata e nelle sue sottodirectory, e visualzza tutte le righe presenti in tali file che contengono una determinata parola chiave P.
Il programma deve attivare due thread,
ad ogni file individuato in una coda bloccante;
di essi, visualizza tutte le righe che contengono la parola chiave P. I due thread si scambiano i dati mediante una coda bloccante. Scegliere il tipo di coda bloccante ritenuto più opportuno.
Per prima cosa, tramite keytool creare le chiavi pubbliche/private con i vostri dati (che andranno associate al server nel keystore) ed estrarre il certificato che va importato in un truststore (sul client). Usando le chiavi svolgere i seguenti esercizi:
In entrambi i casi, dal lato client deve essere presente solo il file con il truststore (non il file con le chiavi). Tutte le password usate (per esempio per il trustore/keystore) NON devono essere inserite nei file sorgenti, ma (per esempio) passate come parametri da riga di comando o inserite a runtime.