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”
Si realizzi un calcolatore asincrono, in grado cioè di calcolare espressioni senza dover attendere la fine di un calcolo prima di accettare l'espressione successiva.
Il programma deve accettare in input un'espressione in una delle seguenti forme:
Ad ogni espressione, il programma aggiunge un task a un threadpool, che effettuerà il calcolo e stamperà il risultato a video, e torna immediatamente a chiedere il prossimo input
I task di calcolo devono stampare, a fine esecuzione: il nome del loro thread, l'istante di creazione, l'istante di inizio esecuzione, l'istante di completamento, e il risultato del calcolo.
Si suggerisce di definire una classe per ogni tipo di task di calcolo, fattorizzando le funzionalità comuni (come la stampa finale) in una superclasse astratta comune.
Soluzione: AsynchronousCalculator.java, Task.java, PITask.java, FibTask.java, FactTask.java
Con riferimento all'esercizio precedente:
“Inserisci espressione: “
Si sperimenti poi con diverse politiche di pooling
Inviare gli esercizi svolti a [email protected] con Subject “[LPR-B] Esercitazione 4”
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 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 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”
fujim2
, fujim3
, …, fujim40
. 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, usando ancora un solo thread, non abbia questo problema, intercalando l'invio di chunks del file al server con la ricezione di pezzi del file compresso.
Si realizzi il client con due thread, uno per la lettura del file originale e l'invio al server, l'altro per la lettura dei dati compressi dal server e la scrittura nel file .gz (si curi, ove necessario, la sincronizzazione fra i due e la gestione degli errori)
Si realizzi il server in modo da poter gestire in maniera efficiente connessioni multiple da parte di più client – si ipotizzi anche che il numero di richieste di servizio possa essere elevato
Quali costrutti per il multithreading sono maggiormente indicati in ciascuno dei due casi di cui sopra?
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.
Utilizzando come protocollo HTTP (come visto nel corso di Reti) sulla porta 80, e come host un web server (per esempio, www.cli.di.unipi.it
o www.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.
La pagina http://en.wikipedia.org/wiki/WAV
contiene alcuni file di esempio di file
audio nel popolare formato WAV (audio non compresso)
/dev/dsp
o /dev/audio
/dev/dsp
è permanentemente occupato da un demone per il mixing audio come esd
, alsa
, pulseaudio
ecc. Può essere necessario uccidere tale demone perché la riproduzione abbia luogo.Non ci si allarmi se l'audio suona “strano”, stiamo trascurando una quantità di parametri…
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.