Skip to content

Instantly share code, notes, and snippets.

@andreacaravano
Created July 1, 2020 12:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreacaravano/407f10e573452826d210c1acd822a7c4 to your computer and use it in GitHub Desktop.
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
/*
* 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.");
}
}
}
/*
* 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