ServerStoAspettando.java
/* 
 * Andrea Caravano (www.andreacaravano.net) 
 * 
 * Esercizio 2: "StoAspettando" 
 * Descrizione: Progettare un’applicazione Client/Server Multithread in Java che attenda, per ogni client collegato, 
 * un numero non precisato di stringhe. L’invio del client termina quando la stringa ricevuta dal server 
 * corrisponde a “FINE-INVIO”. 
 * Prima di concludere la comunicazione, vengono inviate nuovamente al client le stringhe ricevute, trasformate 
 * in maiuscolo. 
 * 
 * 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.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServerStoAspettando {
    static final int PORTALISTEN = 9000;
    static ExecutorService esecutore = Executors.newCachedThreadPool();
    static final String FINESEQUENZA = "FINE-INVIO";

    public static void main(String[] args) {
        try (ServerSocket procServer = new ServerSocket(PORTALISTEN)) {
            System.out.format("Processo server avviato con il seguente indirizzo di socket: %s%n", procServer.getLocalSocketAddress());
            while (true) {
                try {
                    Socket tempSocket = procServer.accept();
                    esecutore.execute(() -> {
                        try (Socket varClient = tempSocket) {
                            System.out.format("Thread ID = %d - Indirizzo di socket del client: %s%n", Thread.currentThread().getId(), varClient.getRemoteSocketAddress());
                            avviaComunicazione(varClient);
                        } catch (IOException e) {
                            System.err.format("Errore di avvio della comunicazione: %s%n", e.getMessage());
                        }
                    });
                } 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 avviaComunicazione(Socket varClient) {
        try (
                BufferedReader BR = new BufferedReader(new InputStreamReader(varClient.getInputStream(), "UTF-8"));
                PrintWriter PW = new PrintWriter(new OutputStreamWriter(varClient.getOutputStream(), "UTF-8"), true)
        ) {
            String stringaRicevuta = BR.readLine();
            int contaStringhe = 0;
            ArrayList<String> listaStringhe = new ArrayList<>();
            while (stringaRicevuta.equals(FINESEQUENZA) == false) {
                contaStringhe++;
                listaStringhe.add(stringaRicevuta);
                stringaRicevuta = BR.readLine();
            }
            PW.println(contaStringhe); // Segnalo al client il numero di stringhe che gli sto per inviare.
            for (String s : listaStringhe) {
                PW.println(s.toUpperCase());
            }
        } catch (IOException e) {
            System.err.format("Errore di I/O: %s%n", e.getMessage());
        }
    }
}