Snippets

Andrea Caravano Esercizio "Linate" dalla raccolta degli esercizi riassuntivi in Java: Socket in TCP e programmazione concorrente

Created by Andrea Caravano
/*
 * 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();
        }
    }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.