Created
July 1, 2020 12:15
-
-
Save andreacaravano/407f10e573452826d210c1acd822a7c4 to your computer and use it in GitHub Desktop.
Esercizio "Linate" dalla raccolta degli esercizi riassuntivi in Java: Socket in TCP e programmazione concorrente
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Andrea Caravano (www.andreacaravano.net) | |
* | |
* Esercizio 4: "Linate" | |
* Descrizione: Il recente processo di ristrutturazione dell’aeroporto di Milano Linate, ha causato un | |
* insolito aumento dei passeggeri nell’aeroporto, causando un incremento del numero di hostess e | |
* manager del check-in che, parallelamente, si occupano di modificare i dettagli di un volo in partenza. | |
* Nel problema proposto, le hostess sono rappresentate due Thread che operano solo quando non stanno operando i | |
* due altri Thread assegnati ai manager del check-in. | |
* Si sottolinea, tuttavia, che le hostess e i manager del check-in, possono operare contemporaneamente | |
* tra di loro, gestendo la modifica dei parametri del volo mediante apposite strutture di gestione della mutua esclusione. | |
* I dettagli del volo su cui operano i due gruppi di Thread sono i seguenti: | |
* 1) Località di partenza: Milano Linate | |
* 2) Località di arrivo: Roma Fiumicino | |
* 3) Data e orario del volo: 18/12/2019 – 09:50 | |
* 4) Incremento di un unità del numero di passeggeri (numero iniziale = 0) | |
* Il server inizia la propria attività solo quando tutti e 4 i client sono connessi. | |
* Attraverso un menù di scelta (che includa anche la possibilità di chiusura della connessione), il client decide | |
* quale operazione attuare e lo comunica al server, che si occuperà di fornire opportuna risposta di conferma. | |
* Si suppone non vi siano vincoli di precedenza. Il primo gruppo di processi che viene avviato, da avvio alle | |
* operazioni di modifica. | |
* | |
* Possibile soluzione | |
* Componente Client | |
* | |
* N.B.: L'esercizio scaturisce dalla sola fantasia dell'autore e intende rappresentare una applicazione didattica. | |
* I dettagli in esso contenuti potrebbero non essere corrispondenti alla realtà e intendono valutare le abilità nella gestione delle strutture dati proposte. | |
*/ | |
import java.io.*; | |
import java.net.Socket; | |
import java.net.UnknownHostException; | |
import java.util.Scanner; | |
class Volo { | |
public String localitaPartenza, localitaArrivo, dataVolo; | |
public int numeroPasseggeri; | |
Volo(String localitaPartenza, String localitaArrivo, String dataVolo, int numeroPasseggeri) { | |
this.localitaPartenza = localitaPartenza; | |
this.localitaArrivo = localitaArrivo; | |
this.dataVolo = dataVolo; | |
this.numeroPasseggeri = numeroPasseggeri; | |
} | |
} | |
public class ClientLinate { | |
static final String INDIRIZZOSERVER = "127.0.0.1"; | |
static final int PORTASERVER = 9000; | |
public static void main(String[] args) { | |
try (Socket processoClient = new Socket(INDIRIZZOSERVER, PORTASERVER)) { | |
System.out.format("Connesso al processo server avviato con il seguente indirizzo di socket: %s%n", processoClient.getRemoteSocketAddress()); | |
System.out.format("Processo client avviato con il seguente indirizzo di socket: %s%n", processoClient.getLocalSocketAddress()); | |
avviaComunicazione(processoClient); | |
} catch (UnknownHostException e) { | |
System.err.println("Server non contattabile. Possibile errore di immissione."); | |
} catch (IOException e) { | |
System.err.format("Errore connessione con server: %s%n", e.getMessage()); | |
} | |
} | |
private static void avviaComunicazione(Socket processoClient) throws IOException { | |
BufferedReader BR = new BufferedReader(new InputStreamReader(processoClient.getInputStream(), "UTF-8")); | |
PrintWriter PW = new PrintWriter(new OutputStreamWriter(processoClient.getOutputStream(), "UTF-8"), true); | |
Scanner S = new Scanner(System.in); | |
System.out.println("AEROPORTO DI MILANO LINATE"); | |
System.out.println("=========================="); | |
System.out.println(); | |
System.out.println("In attesa di iniziare la propria attività..."); | |
System.out.println(); | |
System.out.println("Benvenuto!"); | |
while (BR.readLine().equals("100")) { | |
System.out.println(); | |
System.out.println("Di seguito, le possibili scelte: "); | |
System.out.println("1) Modifica della località di partenza"); | |
System.out.println("2) Modifica della località di arrivo"); | |
System.out.println("3) Modifica dell'orario del volo"); | |
System.out.println("4) Aggiunta di un passeggero"); | |
System.out.println("5) Esci"); | |
System.out.println(); | |
System.out.print("Scelta: "); | |
int scelta = S.nextInt(); | |
S.nextLine(); | |
PW.println(scelta); | |
String risposta = BR.readLine(); | |
if (risposta.equals("405")) { | |
System.err.println("Metodo non consentito. Chiusura della comunicazione..."); | |
break; | |
} else if (risposta.equals("100")) { | |
if (scelta == 1) { | |
System.out.print("Inserisci la nuova località di partenza: "); | |
PW.println(S.nextLine()); | |
} else if (scelta == 2) { | |
System.out.print("Inserisci la nuova località di arrivo: "); | |
PW.println(S.nextLine()); | |
} else if (scelta == 3) { | |
System.out.print("Inserisci la nuova data del volo: "); | |
PW.println(S.nextLine()); | |
} | |
risposta = BR.readLine(); | |
if (risposta.equals("200")) { | |
System.out.println("Modifica accettata."); | |
} else if (risposta.equals("202") && scelta == 5) { | |
System.out.println("Richiesta di chiusura della comunicazione accettata."); | |
break; | |
} | |
} else | |
System.err.println("Errore nella comunicazione."); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Andrea Caravano (www.andreacaravano.net) | |
* | |
* Esercizio 4: "Linate" | |
* Descrizione: Il recente processo di ristrutturazione dell’aeroporto di Milano Linate, ha causato un | |
* insolito aumento dei passeggeri nell’aeroporto, causando un incremento del numero di hostess e | |
* manager del check-in che, parallelamente, si occupano di modificare i dettagli di un volo in partenza. | |
* Nel problema proposto, le hostess sono rappresentate due Thread che operano solo quando non stanno operando i | |
* due altri Thread assegnati ai manager del check-in. | |
* Si sottolinea, tuttavia, che le hostess e i manager del check-in, possono operare contemporaneamente | |
* tra di loro, gestendo la modifica dei parametri del volo mediante apposite strutture di gestione della mutua esclusione. | |
* I dettagli del volo su cui operano i due gruppi di Thread sono i seguenti: | |
* 1) Località di partenza: Milano Linate | |
* 2) Località di arrivo: Roma Fiumicino | |
* 3) Data e orario del volo: 18/12/2019 – 09:50 | |
* 4) Incremento di un unità del numero di passeggeri (numero iniziale = 0) | |
* Il server inizia la propria attività solo quando tutti e 4 i client sono connessi. | |
* Attraverso un menù di scelta (che includa anche la possibilità di chiusura della connessione), il client decide | |
* quale operazione attuare e lo comunica al server, che si occuperà di fornire opportuna risposta di conferma. | |
* Si suppone non vi siano vincoli di precedenza. Il primo gruppo di processi che viene avviato, da avvio alle | |
* operazioni di modifica. | |
* | |
* Possibile soluzione | |
* Componente Server | |
* | |
* N.B.: L'esercizio scaturisce dalla sola fantasia dell'autore e intende rappresentare una applicazione didattica. | |
* I dettagli in esso contenuti potrebbero non essere corrispondenti alla realtà e intendono valutare le abilità nella gestione delle strutture dati proposte. | |
*/ | |
import java.io.*; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import java.net.SocketTimeoutException; | |
import java.util.Scanner; | |
import java.util.concurrent.CountDownLatch; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.Semaphore; | |
import java.util.concurrent.locks.Lock; | |
import java.util.concurrent.locks.ReentrantLock; | |
class Volo { | |
public String localitaPartenza, localitaArrivo, dataVolo; | |
public int numeroPasseggeri; | |
Volo(String localitaPartenza, String localitaArrivo, String dataVolo, int numeroPasseggeri) { | |
this.localitaPartenza = localitaPartenza; | |
this.localitaArrivo = localitaArrivo; | |
this.dataVolo = dataVolo; | |
this.numeroPasseggeri = numeroPasseggeri; | |
} | |
public void stampaInfoVolo() { | |
System.out.println("Informazioni sul volo:"); | |
System.out.format("\tLocalità di partenza: %s%n", localitaPartenza); | |
System.out.format("\tLocalità di arrivo: %s%n", localitaArrivo); | |
System.out.format("\tData del volo: %s%n", dataVolo); | |
System.out.format("\tNumero di passeggeri: %s%n", numeroPasseggeri); | |
} | |
} | |
public class ServerLinate { | |
static final int PORTALISTEN = 9000; | |
static ExecutorService esecutore = Executors.newCachedThreadPool(); | |
static final int TEMPOCONTROLLO = 5000; | |
static final int MINCLIENT = 4; | |
static boolean aspettaClient = true; | |
static int processiAvviati = 0; | |
static CountDownLatch cdlAvvio = new CountDownLatch(1); | |
static Lock mutexManager = new ReentrantLock(); | |
static Lock mutexHostess = new ReentrantLock(); | |
static Semaphore mutex = new Semaphore(1); | |
static Lock mutexVariazioni = new ReentrantLock(); | |
static int processiDentroGruppoManager = 0; | |
static int processiDentroGruppoHostess = 0; | |
static Volo volo = new Volo("Milano Linate", "Roma Fiumicino", "18/12/2019 - 09:50", 0); | |
public static void main(String[] args) { | |
try (ServerSocket procServer = new ServerSocket(PORTALISTEN)) { | |
procServer.setSoTimeout(5000); | |
System.out.format("Processo server avviato con il seguente indirizzo di socket: %s%n", procServer.getLocalSocketAddress()); | |
while (aspettaClient) { | |
try { | |
Socket tempSocket = procServer.accept(); | |
processiAvviati++; | |
if (processiAvviati <= MINCLIENT / 2) { | |
esecutore.execute(() -> { | |
try (Socket varClient = tempSocket) { | |
System.out.format("Thread ID = %d - Indirizzo di socket del client: %s%n", Thread.currentThread().getId(), varClient.getRemoteSocketAddress()); | |
manager(varClient); | |
} catch (IOException e) { | |
System.err.format("Errore di avvio della comunicazione: %s%n", e.getMessage()); | |
} | |
}); | |
} else { | |
esecutore.execute(() -> { | |
try (Socket varClient = tempSocket) { | |
System.out.format("Thread ID = %d - Indirizzo di socket del client: %s%n", Thread.currentThread().getId(), varClient.getRemoteSocketAddress()); | |
hostess(varClient); | |
} catch (IOException e) { | |
System.err.format("Errore di avvio della comunicazione: %s%n", e.getMessage()); | |
} | |
}); | |
} | |
} catch (SocketTimeoutException e) { | |
if (processiAvviati >= MINCLIENT) { | |
aspettaClient = false; | |
cdlAvvio.countDown(); | |
} else { | |
System.err.println("Ancora non è stato raggiunto il numero di client minimo."); | |
} | |
} catch (IOException e) { | |
System.err.format("Errore nella creazione di nuovi socket: %s%n", e.getMessage()); | |
} | |
} | |
} catch (IOException e) { | |
System.err.format("Errore lato server: %s%n", e.getMessage()); | |
} | |
} | |
private static void manager(Socket varClient) { | |
try ( | |
BufferedReader BR = new BufferedReader(new InputStreamReader(varClient.getInputStream(), "UTF-8")); | |
PrintWriter PW = new PrintWriter(new OutputStreamWriter(varClient.getOutputStream(), "UTF-8"), true) | |
) { | |
cdlAvvio.await(); | |
mutexManager.lock(); | |
try { | |
processiDentroGruppoManager++; | |
if (processiDentroGruppoManager == 1) { | |
mutex.acquire(); | |
} | |
System.out.format("Il manager n. %d ha avviato la propria attività%n", processiDentroGruppoManager); | |
} finally { | |
mutexManager.unlock(); | |
} | |
PW.println("100"); // Tratto da HTTP: "Continue" | |
comunica(BR, PW); | |
mutexManager.lock(); | |
try { | |
processiDentroGruppoManager--; | |
if (processiDentroGruppoManager == 0) { | |
mutex.release(); | |
} | |
} finally { | |
mutexManager.unlock(); | |
} | |
} catch (IOException e) { | |
System.err.format("Errore di I/O: %s%n", e.getMessage()); | |
} catch (InterruptedException e) { | |
System.err.format("Errore di gestione dei meccanismi della programmazione concorrente: %s%n", e.getMessage()); | |
} | |
} | |
private static void hostess(Socket varClient) { | |
try ( | |
BufferedReader BR = new BufferedReader(new InputStreamReader(varClient.getInputStream(), "UTF-8")); | |
PrintWriter PW = new PrintWriter(new OutputStreamWriter(varClient.getOutputStream(), "UTF-8"), true) | |
) { | |
cdlAvvio.await(); | |
mutexHostess.lock(); | |
try { | |
processiDentroGruppoHostess++; | |
if (processiDentroGruppoHostess == 1) { | |
mutex.acquire(); | |
} | |
System.out.format("La hostess n. %d ha avviato la propria attività%n", processiDentroGruppoHostess); | |
} finally { | |
mutexHostess.unlock(); | |
} | |
PW.println("100"); // Tratto da HTTP: "Continue" | |
comunica(BR, PW); | |
mutexHostess.lock(); | |
try { | |
processiDentroGruppoHostess--; | |
if (processiDentroGruppoHostess == 0) { | |
mutex.release(); | |
} | |
} finally { | |
mutexHostess.unlock(); | |
} | |
} catch (IOException e) { | |
System.err.format("Errore di I/O: %s%n", e.getMessage()); | |
} catch (InterruptedException e) { | |
System.err.format("Errore di gestione dei meccanismi della programmazione concorrente: %s%n", e.getMessage()); | |
} | |
} | |
private static void comunica(BufferedReader BR, PrintWriter PW) throws IOException { | |
int scelta = new Scanner(BR.readLine()).nextInt(); | |
while (true) { | |
if (scelta == 1) { | |
PW.println("100"); | |
mutexVariazioni.lock(); | |
try { | |
volo.localitaPartenza = BR.readLine(); | |
PW.println("200"); // Tratto da HTTP: "OK" | |
} finally { | |
mutexVariazioni.unlock(); | |
} | |
} else if (scelta == 2) { | |
PW.println("100"); | |
mutexVariazioni.lock(); | |
try { | |
volo.localitaArrivo = BR.readLine(); | |
PW.println("200"); | |
} finally { | |
mutexVariazioni.unlock(); | |
} | |
} else if (scelta == 3) { | |
PW.println("100"); | |
mutexVariazioni.lock(); | |
try { | |
volo.dataVolo = BR.readLine(); | |
PW.println("200"); | |
} finally { | |
mutexVariazioni.unlock(); | |
} | |
} else if (scelta == 4) { | |
PW.println("100"); | |
mutexVariazioni.lock(); | |
try { | |
volo.numeroPasseggeri++; | |
PW.println("200"); | |
} finally { | |
mutexVariazioni.unlock(); | |
} | |
} else if (scelta == 5) { | |
PW.println("100"); // Tratto da HTTP: "Continue" | |
PW.println("202"); // Tratto da HTTP: "Accepted" | |
break; | |
} else { | |
PW.println("405"); // Tratto da HTTP: "Method not allowed" | |
} | |
volo.stampaInfoVolo(); | |
PW.println("100"); | |
scelta = new Scanner(BR.readLine()).nextInt(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment