Snippets
Andrea Caravano Esercizio "Telegiornale" dalla raccolta degli esercizi riassuntivi in Java: Socket in TCP e programmazione concorrente
Created by
Andrea Caravano
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | /*
* Andrea Caravano (www.andreacaravano.net)
*
* Esercizio 5: "Telegiornale"
* Descrizione: La redazione di TGJava24 ha adottato un’infrastruttura di rete che prevede un numero variabile
* di assistenti alla regia e redattori che hanno la necessità di comunicare con il giornalista in onda in tempo reale,
* per informarlo su eventuali variazioni e/o correzioni alle notizie oggetto del telegiornale.
* Si suppone che il primo client che si collega sia il giornalista in onda e tutti i successivi siano assistenti alla
* regia e redattori.
* Un possibile esempio di variazione alle notizie comunicata dai redattori può essere la seguente:
* Traffico intenso sulla A14
* A causa delle recenti manifestazioni nell’area di Bologna, un’insolita coda si è formata all’altezza del
* chilometro 721 dell’autostrada A14.
* La struttura della notizia deve includere il titolo della notizia (su una sola linea) e il testo esteso della notizia,
* multilinea. Il client del giornalista dovrà rimanere costantemente in ascolto di eventuali variazioni comunicate
* dai redattori.
*
* Sviluppare la sola 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.List;
import java.util.Map;
import java.util.TreeMap;
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;
public class ServerTelegiornale {
static final int PORTALISTEN = 9000;
static int contaClient = 0;
static ExecutorService esecutore = Executors.newCachedThreadPool();
static Lock mutexLettori = new ReentrantLock();
static Lock mutexScrittori = new ReentrantLock();
static Semaphore semLettura = new Semaphore(1);
static Semaphore sincro = new Semaphore(1);
static int processiDentroScrittori = 0;
static int processiDentroLettori = 0;
static TreeMap<String, List<String>> notizie = new TreeMap<>();
public static void main(String[] args) {
System.out.println("TGJava24 - REDAZIONE");
System.out.println("====================");
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 tempClient = procServer.accept();
contaClient++;
if (contaClient == 1) {
esecutore.execute(() -> {
try (Socket client = tempClient) {
System.out.format("Thread ID = %d - Indirizzo di socket del client: %s%n", Thread.currentThread().getId(), client.getRemoteSocketAddress());
lettore(client);
} catch (IOException e) {
System.err.format("Errore di avvio della comunicazione: %s%n", e.getMessage());
}
});
} else {
esecutore.execute(() -> {
try (Socket client = tempClient) {
System.out.format("Thread ID = %d - Indirizzo di socket del client: %s%n", Thread.currentThread().getId(), client.getRemoteSocketAddress());
scrittore(client);
} 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 scrittore(Socket client) {
try (BufferedReader BR = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
PrintWriter PW = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"), true)) {
System.out.println("Thread scrittore avviato.");
PW.println("RUOLO = Scrittore");
while (true) {
String titoloNotiziaLocale = BR.readLine();
List<String> testoNotiziaLocale = new ArrayList<>();
String singolaRiga;
do {
singolaRiga = BR.readLine();
if (singolaRiga.isEmpty() == false)
testoNotiziaLocale.add(singolaRiga);
} while (singolaRiga.isEmpty() == false);
System.out.println("Presa in carico una nuova notizia.");
PW.println("202"); // Tratto da HTTP: "Accepted"
inizioScrittura();
notizie.put(titoloNotiziaLocale, testoNotiziaLocale);
fineScrittura();
}
} catch (UnsupportedEncodingException e) {
System.out.format("Errore: codifica non supportata: %s", e.getMessage());
} 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 lettore(Socket client) {
try (BufferedReader BR = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
PrintWriter PW = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"), true)) {
System.out.println("Thread lettore avviato.");
PW.println("RUOLO = Lettore");
TreeMap<String, List<String>> notizieInviate = new TreeMap<>();
while (true) {
inizioLettura();
for (Map.Entry<String, List<String>> n : notizie.entrySet()) {
if (notizieInviate.containsKey(n.getKey()) == false) {
PW.println(n.getKey());
List<String> righeNotizia = n.getValue();
for (String r : righeNotizia) {
PW.println(r);
}
notizieInviate.put(n.getKey(), n.getValue());
}
}
fineLettura();
}
} catch (UnsupportedEncodingException e) {
System.out.format("Errore: codifica non supportata: %s", e.getMessage());
} 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 fineLettura() throws InterruptedException {
mutexLettori.lock();
try {
processiDentroLettori--;
if (processiDentroLettori == 0) {
sincro.release();
}
} finally {
mutexLettori.unlock();
}
}
private static void inizioLettura() throws InterruptedException {
semLettura.acquire();
mutexLettori.lock();
try {
processiDentroLettori++;
if (processiDentroLettori == 1) {
sincro.acquire();
}
} finally {
mutexLettori.unlock();
semLettura.release();
}
}
private static void inizioScrittura() throws InterruptedException {
mutexScrittori.lock();
try {
processiDentroScrittori++;
if (processiDentroScrittori == 1) {
semLettura.acquire();
}
sincro.acquire();
} finally {
mutexScrittori.unlock();
}
}
private static void fineScrittura() throws InterruptedException {
mutexScrittori.lock();
try {
sincro.release();
processiDentroScrittori--;
if (processiDentroScrittori == 0) {
semLettura.release();
}
} finally {
mutexScrittori.unlock();
}
}
}
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.