[:it]
Costruire un’applicazione client/server che realizza una chat, consentendo di scambiare messaggi tra un client e un server. Il client può terminare la connessione inserendo la parola FINE.
La chat viene realizzata con due programmi di rete: un programma server e un programma client. Le due persone che vogliono partecipare alla chat devono disporre di uno dei due programmi. La persona che esegue il programma server resta in attesa che l’altra persona si colleghi usando il programma client. Quando la connessione è stata attivata, la chat può avere inizio.
Si suppone che la chat venga eseguita all’interno della finestra del Prompt dei comandi di Windows o nella finestra Terminale di Linux. I messaggi da inviare vengono letti da tastiera e i messaggi ricevuti vengono visualizzati all’interno della finestra. Dopo aver stabilito la connessione, la chat viene gestita in modo sequenziale, cioè le operazioni sono svolte nel seguente ordine, stabilendo un protocollo di comunicazione:
[client]: legge il messaggio da tastiera e lo invia al server.
[server]: riceve il messaggio e lo visualizza.
[server]: legge il messaggio da tastiera e lo invia al client.
[client]: riceve il messaggio e lo visualizza.
La sequenza precedente viene realizzata con un ciclo infinito sia sul client che sul server. Il ciclo nel programma client termina quando si inserisce da tastiera la parola FINE, come mostra il seguente frammento di codice.
while (true) {
// legge il messaggio da tastiera
msgDaInviare = tastiera.readLine();
// interrompe la chat
if (msgDaInviare.equals(“FINE”))
break;
// invia il messaggio al server
// riceve il messaggio e lo visualizza
}
Si osservi che anche la parola FINE rappresenta un elemento del protocollo di comunicazione.
Il ciclo nel programma server termina quando viene ricevuto il valore null dal flusso di input della socket. Questo indica che il client si è sconnesso.
while (true) {
// riceve il messaggio
msgRicevuto = sIN.readLine();
if (msgRicevuto == null)
{ System.out.println(“Il client ha chiuso la chat.”);
break; }
// visualizza il messaggio
// legge il messaggio da tastiera
// invia il messaggio al client
}
Sia il client che il server devono gestire tre flussi di dati: – flusso di lettura di dati da tastiera – flusso di lettura di dati dalla socket – flusso di scrittura di dati sulla socket.
Questi tre flussi sono gestiti usando i seguenti oggetti:
In particolare il server deve inizializzare i flussi nel seguente ordine:
// flusso in uscita su socket
out = connessione.getOutputStream();
sOUT = new PrintWriter(out);
// flusso in ingresso da socket
in = new InputStreamReader(connessione.getInputStream());
sIN = new BufferedReader(in);
// flusso in ingresso da tastiera
input = new InputStreamReader(System.in);
tastiera = new BufferedReader(input);
Il client deve inizializzare i flussi nel seguente ordine:
// flusso in ingresso da socket
in = new InputStreamReader(connessione.getInputStream());
sIN = new BufferedReader(in);
// flusso in uscita su socket out = connessione.getOutputStream();
sOUT = new PrintWriter(out);
// flusso in ingresso da tastiera
input = new InputStreamReader(System.in);
tastiera = new BufferedReader(input);
Come si può notare il server inizializza prima il flusso in uscita e poi il flusso in ingresso, mentre il client fa l’opposto.
Per fare in modo che l’invio dei messaggi avvenga immediatamente si devono usare le seguenti istruzioni:
sOUT.println(msgDaInviare);
sOUT.flush();
Il metodo flush serve per svuotare il buffer del flusso di output e inviare i dati. Di seguito sono riportati i programmi completi, lato server e lato client.
Ecco il sorgente sa parte server:
// chat con una sola connessione
import java.net.*;
import java.io.*;
public class ServerChat {
public static void main(String args[])
{
ServerSocket sSocket;
Socket connessione = null;
int port = 2345;
InputStreamReader in, input;
BufferedReader sIN, tastiera;
OutputStream out;
PrintWriter sOUT;
String msgDaInviare;
String msgRicevuto;
try
{
sSocket = new ServerSocket(port);
System.out.println(“In attesa di connessioni…”);
// ciclo infinito
while (true)
{
connessione = sSocket.accept();
// flusso in uscita su socket
out = connessione.getOutputStream();
sOUT = new PrintWriter(out);
// flusso in ingresso da socket
in = new InputStreamReader(connessione.getInputStream());
sIN = new BufferedReader(in);
// flusso in ingresso da tastiera
input = new InputStreamReader(System.in);
tastiera = new BufferedReader(input);
System.out.println(“Chat inizializzata.”);
while (true) {
// stampa il messaggio ricevuto
msgRicevuto = sIN.readLine();
if (msgRicevuto == null)
{
System.out.println(“Il client ha chiuso la chat.”);
break;
}
System.out.println(“>> ” + msgRicevuto);
// legge il messaggio da tastiera
msgDaInviare = tastiera.readLine();
// invia il messaggio
sOUT.println(msgDaInviare);
sOUT.flush();
}
}
}
catch (IOException e)
{ System.out.println(e); }
try { connessione.close(); }
catch (IOException e)
{ System.out.println(e); }
}import java.net.*;
import java.io.*;
public class ClientChat {
public static void main(String[] args)
{
Socket connessione = null;
String server = “localhost”;
int port = 2345;
InputStreamReader in, input;
BufferedReader sIN, tastiera;
OutputStream out;
PrintWriter sOUT;
String msgDaInviare;
String msgRicevuto;
try {
connessione = new Socket(server, port);
System.out.println(“Connessione eseguita.”);
}
catch (IOException e)
{
System.out.println(e);
System.exit(-1);
}
try {
// flusso in ingresso da socket
in = new InputStreamReader(connessione.getInputStream());
sIN = new BufferedReader(in);
// flusso in uscita su socket
out = connessione.getOutputStream();
sOUT = new PrintWriter(out);
// flusso in ingresso da tastiera
input = new InputStreamReader(System.in);
tastiera = new BufferedReader(input);
System.out.println(“Chat inizializzata.”);
while (true)
{
// legge il messaggio da tastiera
msgDaInviare = tastiera.readLine();
// interrompe la chat
if (msgDaInviare.equals(“FINE”)) break;
// invia il messaggio
sOUT.println(msgDaInviare);
sOUT.flush();
// stampa il messaggio ricevuto
msgRicevuto = sIN.readLine();
System.out.println(“>> ” + msgRicevuto);
}
}
catch (IOException e)
{
System.out.println(e);
}
try {
connessione.close();
}
catch (IOException e)
{
System.out.println(e);
}
}
}
Ecco il sorgente da parte client:
import java.net.*;
import java.io.*;
public class ClientChat {
public static void main(String[] args)
{
Socket connessione = null;
String server = “localhost”;
int port = 2345;
InputStreamReader in, input;
BufferedReader sIN, tastiera;
OutputStream out;
PrintWriter sOUT;
String msgDaInviare;
String msgRicevuto;
try {
connessione = new Socket(server, port);
System.out.println(“Connessione eseguita.”);
}
catch (IOException e)
{
System.out.println(e);
System.exit(-1);
}
try {
// flusso in ingresso da socket
in = new InputStreamReader(connessione.getInputStream());
sIN = new BufferedReader(in);
// flusso in uscita su socket
out = connessione.getOutputStream();
sOUT = new PrintWriter(out);
// flusso in ingresso da tastiera
input = new InputStreamReader(System.in);
tastiera = new BufferedReader(input);
System.out.println(“Chat inizializzata.”);
while (true)
{
// legge il messaggio da tastiera
msgDaInviare = tastiera.readLine();
// interrompe la chat
if (msgDaInviare.equals(“FINE”)) break;
// invia il messaggio
sOUT.println(msgDaInviare);
sOUT.flush();
// stampa il messaggio ricevuto
msgRicevuto = sIN.readLine();
System.out.println(“>> ” + msgRicevuto);
}
}
catch (IOException e)
{
System.out.println(e);
}
try {
connessione.close();
}
catch (IOException e)
{
System.out.println(e);
}
}
}
[:]