Dezvoltarea sistemelor software complexe este de obicei realizata in mai
multe iteratii in
care:
- sunt reluate activitatile de analiza, proiectare, implementare,
testare,
- sunt adaugate activitatile de
- evaluare a iteratiei anterioare si de
- planificare a iteratiilor ulterioare.
Rezultatele iteratiei anterioare sunt fie o
versiune a sistemului software, fie doar un prototip al acestuia.
Evaluarea rezultatelor iteratiei anterioare consta, printre altele, din:
- verificarea functionarii corecte a sistemului (conformitatii cu
specificatiile),
- evaluarea documentatiei si a
codului (analiza codului),
- evaluarea gradului in care versiunea obtinuta corespunde asteptarilor
utilizatorilor.
In ceea ce priveste evaluarea sistemului de comunicatie pentru conversatie
textuala, dezvoltat in iteratia anterioara, pot fi facute, printre altele,
urmatoarele observatii:
- interfata grafica
este rudimentara,
modul de conectare la server putand fi imbunatatit,
- utilizatorii
sunt identificati pe baza numelui de utilizator de pe masina pe care ei
lanseaza componentele client, in loc sa isi poata alege un nume de utilizator
al sistemului de conversatie (nickname)
- bara
de defilare a zonei de text ar fi preferabil sa fie in mod automat actualizata
astfel incat sa fie vizibile intotdeauna ultimele mesaje primite,
- utilizatorii nu au
nici o informatie despre ceilalti utilizatori prezenti in conversatie
- pe un server poate
exista doar un singur grup de utilizatori la un moment dat (alternativa ar fi
posibilitatea crearii unor “camere”, grupuri, etc.)
- nu exista
posibilitatea crearii unor canale de comunicatie private, pentru conversatia
intre 2 utilizatori
- etc. (lista va fi
largita prin discutii la laborator/proiect).
In urma acestei evaluari, presupunem ca s-a decis ca
in iteratia urmatoare sa fie realizate urmatoarele imbunatatiri:
- posibilitatea oferita utilizatorilor de a-si alege un nume de
utilizator (nickname)
- actualizarea automata a barei de defilare a zonei de text pentru ca
ultimele mesaje primite sa fie vizibile
- difuzarea de catre server a numelor de utilizator catre toti
utilizatorii si informarea de catre client a utilizatorilor despre modificarile
in componenta grupului de utilizatori
Desigur, raman nerezolvate anumite posibile cerinte ale
utilizatorilor,
cum ar fi
- posibilitatea crearii mai multor
“camere” sau grupuri pe un server
- posibilitatea crearii unor canale
de comunicatie private
- etc (lista va fi largita prin discutii la laborator/proiect).
Actualizarea analizei OO presupune:
- actualizarea diagramei UML a
cazurilor de utilizare,
- actualizarea descrierii cazurilor
de utilizare
- actualizarea listei claselor
principale ale sistemului
- actualizarea diagramelor UML de
secventa care descriu scenariile componente ale cazurilor de utilizare
- actualizarea diagramelor UML de
colaborare corespunzatoare
Varianta de nivel inalt a diagramei de secventa pentru scenariul conectarii unui nou client.
Varianta de nivel inalt a diagramei de secventa pentru scenariul deconectarii unui client.
Varianta de nivel inalt a diagramei de secventa pentru scenariul conversatiei intre clienti.
Actualizarea proiectarii OO presupune:
- actualizarea proiectarii
interfetei grafice cu utilizatorul
- actualizarea diagramelor UML de
secventa si de colaborare
- actualizarea diagramelor UML de
clase
- actualizarea diagramelor UML de
stari
- actualizarea diagramelor UML de
activitati
Interfata grafica prezentata initial unui nou utilizator, pentru alegerea numelui in vederea
conectarii, este o fereastra de dialog:
In cazul in care utilizatorul propune un nume care exista deja in lista
serverului, acesta
respinge inregistrarea iar clientul
prezinta urmatoarea fereastra de dialog:
Presupunem urmatorul scenariu:
- primul utilizator isi alege numele
isw2004,
- al doilea utilizator isi alege
numele swrtc2004 (moment in care
ambii utilizatori sunt informati, unul de existenta celuilalt),
- cei doi utilizatori schimba cateva
mesaje,
- se conecteaza al treilea
utilizator, care isi alege numele rtc2004
(moment in care primii doi utilizatori sunt informati de existenta celui
de-al treilea, iar acesta de existenta celorlalti doi),
- cei trei utilizatori schimba
cateva mesaje,
- utilizatorul cu numele swrtc2004 paraseste conversatia (moment
in care ceilalti doi utilizatori sunt informati).
Continutul interfetei grafice pentru cei trei utilizatori va fi urmatorul:
- pentru utilizatorul cu numele swrtc2004:
- pentru utilizatorul cu numele isw2004:
- pentru utilizatorul cu numele rtc2004:
Diagrama de clase actualizata a clientului este urmatoarea:
Diagrama de clase actualizata a serverului este urmatoarea:
Codul sursa Java pentru clientul
de chat (si fisierul
pentru compilarea si lansarea clientului)
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 00 01 02 03 04 05 06 07 08 09 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 00 01 02 03 04 05 06 07 08 09 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 00 01 02 03 04 05 06 07 08 09 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 00 01 02 03 04 05 06 07 08 09 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 |
//Source
file: ClientDeChat_v2.java import java.net.*; import java.io.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.Properties; /** * Client de
chat simplu - aplicatie de sine statatoare * Aplicatie grafica Swing (extinde JFrame) * care poate lansa in executie un fir nou
(implementeaza Runnable) */ public class
ClientDeChat_v2 extends JFrame implements Runnable { private
String numeUser; private
String adresaLocala; private
int portLocal; /** * Vector
de obiecte cu informatii privind ceilalti clienti */ private
static Vector altiClienti = new Vector (); /** * Flux de
intrare dinspre retea */ private DataInputStream
inRetea; /** * Zona de
text (configurata ca non-editabila) */ private
JTextArea outTextGrafic; /** * Intrare
de text (editabila) */ private
JTextField inTextGrafic; /** * Fir de
executie */ private
Thread firReceptie; /** * Socket
flux (TCP) */ private
static Socket socket; /** * Flux de
iesire catre retea */ private
DataOutputStream outRetea; private
InetAddress iaLocala; JScrollBar
baraDefilareVerticala; /** * Initializeaza
obiectul de tip ClientDeChat_v1 * @param
title Titlul ferestrei * @param
inRetea Flux de intrare dinspre
retea * @param
outRetea Flux de iesire catre retea */ public ClientDeChat_v2(String title,
InputStream inRetea,
OutputStream outRetea) { //
Stabilire titlu fereastra (JFrame)
super(); //
---------------------------------------------------------------- //
Trimiterea catre server a informatiilor privind clientul //
----------------------------------------------------------------
this.inRetea = new DataInputStream (new BufferedInputStream
(inRetea));
this.outRetea = new DataOutputStream (new BufferedOutputStream (outRetea)); //
----------------------------------------------------------------------- //
Afisarea in consola si trimiterea catre server a info. privind clientul //
----------------------------------------------------------------------- // Obtinerea
numarului de port local
portLocal = this.socket.getLocalPort(); try { //
Obtinerea adresei locale ca obiect InetAddress
iaLocala = InetAddress.getLocalHost(); //
Obtinerea formei String a adresei locale
adresaLocala = iaLocala.getHostAddress();
System.out.println("\n Clientul are adresa " + adresaLocala
+ " si portul
" + portLocal); //
Scrierea adresei IP pe fluxul de iesire spre retea
this.outRetea.writeUTF(adresaLocala); //
Scrierea portului TCP pe fluxul de iesire spre retea
this.outRetea.writeInt(portLocal); //
-------------------------------------------------------------- //
Trimiterea (si eventual modificarea) numelui utilizatorului //
--------------------------------------------------------------
boolean existaDeja; String
mesajDialog = "Alegeti numele de utilizator!"; do { //
Alegerea numelui de utilizator numeUser
= JOptionPane.showInputDialog(mesajDialog); //
Scrierea numelui utilizatorului pe fluxul de iesire spre retea
this.outRetea.writeUTF(numeUser); //
Fortarea trimiterii (fortarea golirii bufferului)
this.outRetea.flush ();
//
Citirea rezultatului din fluxul de intrare dinspre retea
String rezultat = this.inRetea.readUTF();
existaDeja = rezultat.equals("Numele a fost deja alocat");
mesajDialog = "Numele ales exista deja. Alegeti alt nume!"; } while (existaDeja);
System.out.println("\n Clientul are numele " + numeUser); } //
-------------------------------------------------------------- //
Tratarea erorilor de conexiune //
-------------------------------------------------------------- catch (IOException ex) { //
Afisarea exceptiei
ex.printStackTrace(); } //
-------------------------------------------------------------- //
Initializari grafice // --------------------------------------------------------------
this.setTitle("Client
" + numeUser + " : " + title);
Container containerCurent = this.getContentPane();
containerCurent.setLayout(new BorderLayout()); // Zona
de text non-editabila de iesire (cu posibilitati de defilare)
outTextGrafic = new JTextArea(8, 40);
JScrollPane panouDefilabil = new JScrollPane(outTextGrafic,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
baraDefilareVerticala = panouDefilabil.getVerticalScrollBar();
containerCurent.add("Center", panouDefilabil);
outTextGrafic.setEditable (false); // Camp
de text editabil de intrare inTextGrafic
= new JTextField(40);
containerCurent.add("South", inTextGrafic);
System.out.println("\n Configurata interfata grafica
\n"); //
-------------------------------------------------------------- // Tratarea
evenimentelor interfetei grafice (intrarea de text) //
-------------------------------------------------------------- //
Variabila locala finala (folosita in clasa interna anonima de tip //
ActionListener) final
DataOutputStream outR = this.outRetea; //
Crearea unui "ascultator" de "evenimente actionare"
ActionListener ascultatorInText = new ActionListener() { //
Tratarea actionarii intrarii de text (apasarea tastei "Enter") public
void actionPerformed(ActionEvent ev) { //
Citire mesajului din intrarea de text
String intrare = inTextGrafic.getText(); try { //
Scrierea mesajului pe fluxul de iesire spre retea
outR.writeUTF(numeUser + " [" + adresaLocala + ":"
+ portLocal + "]> " +
intrare); //
Fortarea trimiterii mesajului (fortarea golirii bufferului)
outR.flush (); } // In cazul unei erori legata de conexiune catch (IOException ex) { //
Afisarea exceptiei
ex.printStackTrace(); //
Inchiderea firului de executie care efectueaza receptia
firReceptie = null; } //
Pregatirea intrarii de text pentru noul mesaj (golirea intrarii)
inTextGrafic.setText (""); } }; //
Inregistrarea "ascultatorului" de "evenimente actionare"
la //
"obiectul sursa" intrare text
inTextGrafic.addActionListener(ascultatorInText); //
---------------------------------------------------------------- //
Tratarea evenimentelor interfetei grafice (inchiderea ferestrei) //
---------------------------------------------------------------- //
Crearea unui "adaptor pentru ascultator" de "evenimente
fereastra"
WindowAdapter ascultatorInchidere = new WindowAdapter() { //
Tratarea inchiderii ferestrei curente public
void windowClosing(WindowEvent ev) { //
Daca mai exista firul de executie de receptie if (firReceptie != null) { //
Inchiderea firului de receptie
firReceptie = null;
} //
Terminarea programului
System.exit(0);
} }; //
Inregistrarea "ascultatorului" de "evenimente fereastra"
la "sursa" //
(fereastra curenta)
this.addWindowListener(ascultatorInchidere); //
-------------------------------------------------------------- //
Lansarea interfetei grafice //
-------------------------------------------------------------- //
Impachetarea (compactarea) componentelor in container
pack();
//
Fereastra devine vizibila - echivalent cu frame.setVisible(true)
show(); //
Cerere focus pe intrarea de text din fereastra curenta
inTextGrafic.requestFocus(); //
-------------------------------------------------------------- //
Lansarea firului de executie de receptie //
-------------------------------------------------------------- // Fir
de executie pentru receptia mesajelor de la server
firReceptie = new Thread (this); //
Lansarea firului de executie - se executa run()
firReceptie.start (); } /** * Metoda
principala a firului care receptioneaza mesaje de la server */ public void run() { //
-------------------------------------------------------------- // Tratarea
mesajelor serverului (citirea si interpretarea lor) //
-------------------------------------------------------------- try { while (true) { //
Citirea mesajului din fluxul de intrare dinspre server
String line = inRetea.readUTF (); //
-------------------------------------------------------------- //
Inregistrarea unui client nou sau preexistent //
-------------------------------------------------------------- if (line.equals("Client
nou")) { //
Citirea mesajului din fluxul de intrare dinspre server
String numeClient = inRetea.readUTF (); //
Citirea mesajului din fluxul de intrare dinspre server String
adresaClient = inRetea.readUTF ();
//
Citirea mesajului din fluxul de intrare dinspre server
int portClient = Integer.parseInt(inRetea.readUTF()); //
Incapsularea informatiilor privind clientul InfoClient clientNou = new
InfoClient(numeClient, adresaClient, portClient); //
Inregistrarea clientului curent in lista (Vector)
altiClienti.addElement (clientNou);
System.out.println("Client nou: " + numeClient + " [" +
adresaClient + " : "
+ portClient + "]");
System.out.println("Lista clientilor:\n" +
altiClienti.toString()); //
Anuntarea in iesirea de text a noului client
outTextGrafic.append ("Participa la conversatie si: " +
numeClient + " [" +
adresaClient + " : "
+ portClient + "] \n"); } //
--------------------------------------------------------------- //
Eliminarea inregistrarii unui client care a parasit conversatia //
--------------------------------------------------------------- else
if (line.equals("Client
eliminat")) { // Citirea mesajului din fluxul de
intrare dinspre server
String numeClient = inRetea.readUTF (); //
Citirea mesajului din fluxul de intrare dinspre server
String adresaClient = inRetea.readUTF (); // Citirea mesajului din fluxul de
intrare dinspre server
int portClient = Integer.parseInt(inRetea.readUTF()); //
Incapsularea informatiilor privind clientul
InfoClient clientEliminat = new InfoClient(numeClient, adresaClient,
portClient);
altiClienti.removeElement (clientEliminat);
System.out.println("Client eliminat: " + numeClient + " [" +
adresaClient + " : "
+ portClient + "]");
System.out.println("Lista clientilor:\n" +
altiClienti.toString()); //
Anuntarea in iesirea de text a eliminarii clientului
outTextGrafic.append ("A parasit conversatia: " + numeClient
+ " [" +
adresaClient + " : "
+ portClient + "] \n"); } //
-------------------------------------------------------------- //
Afisarea mesajului (propriu-zis) receptionat //
-------------------------------------------------------------- else
{ //
Adaugare textului primit in iesirea de text
outTextGrafic.append (line + "\n"); } // Solutie
pentru a avea afisate intotdeauna ultimele //
mesaje primite (exista o solutie alternativa???) int
zonaVizibila = baraDefilareVerticala.getVisibleAmount(); int
valoareaMaxima = baraDefilareVerticala.getMaximum(); baraDefilareVerticala.setValue(valoareaMaxima
- zonaVizibila);
validate();
repaint(); } } //
-------------------------------------------------------------- //
Tratarea erorilor de conexiune //
-------------------------------------------------------------- catch (IOException ex) { //
Afisarea exceptiei
ex.printStackTrace ();
} //
-------------------------------------------------------------- //
Curatenie finala // -------------------------------------------------------------- finally { //
Inchiderea firului de receptie curent
firReceptie = null; //
Ascunderea intrarii de text inTextGrafic.setVisible(false); //
Reasezarea interfetei grafice
validate (); try { //
Inchiderea fluxului de iesire spre retea
outRetea.close ();
} // In
cazul unei erori legata de conexiune catch (IOException ex) { //
Afisarea exceptiei
ex.printStackTrace (); } } } /** * Metoda
principala - creaza socketul, fluxurile si lanseaza clientul * @param args[] * @param args * @throws java.io.IOException */ public static void main(java.lang.String[]
args) throws IOException { //
Adresa serverului String
adresaServer =
JOptionPane.showInputDialog("Introduceti adresa
serverului"); //
Portul serverului String
numarPort = JOptionPane.showInputDialog( "Introduceti
numarul de port al serverului"); int
portServer = Integer.parseInt(numarPort); //
Crearea socketului catre server socket =
new Socket (adresaServer, portServer);
System.out.println ("\n Client TCP lansat catre serverul [" +
socket.getInetAddress() + ":" + socket.getPort() +
"]"); //
Crearea fluxurilor, crearea si lansarea clientului grafic new
ClientDeChat_v2 (socket.getLocalPort() +
" (Server " + adresaServer + " : " +
numarPort + ")", socket.getInputStream
(), socket.getOutputStream ()); } } class InfoClient
{ String nume; String adresa; int port; Thread fir; /** * @param
nume * @param
adresa * @param
port * @param
fir */ public InfoClient(String nume, String
adresa, int port, Thread fir) {
this.nume = nume; this.adresa
= adresa;
this.port = port; this.fir
= fir; } /** * @param
nume * @param
adresa * @param
port * @param
fir */ public InfoClient(String nume, String
adresa, int port) {
this.nume = nume;
this.adresa = adresa;
this.port = port; this.fir
= null; } public
void setFir(Thread fir) { this.fir
= fir; } /** * @return
java.lang.String */ public String toString() { return
"\t" + nume + "/" + adresa + ":" + port +
"\n"; } /** * @return
boolean */ public boolean equals(Object obj) { if ((obj != null) && (obj
instanceof InfoClient)) {
InfoClient celalaltClient = (InfoClient)obj; return
((this.nume.equals(celalaltClient.nume)) &&
(this.adresa.equals(celalaltClient.adresa)) &&
(this.port == celalaltClient.port)); } return
false; } } |
Codul sursa Java pentru serverul
de chat (si fisierul
pentru compilarea si lansarea serverului)
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 |
//Source
file: ServerDeChat_v2.java /** * Server
chat simplu - componenta server pentru noi conexiuni */ import java.net.*; import java.io.*; import java.util.*; public class
ServerDeChat_v2 { private TratareClientDeChat_v2 firTratare; private Socket socket; public ServerDeChat_v2(int port) throws
IOException { // Server pentru asteptarea cererilor de
conectare
ServerSocket server = new ServerSocket (port);
System.out.println ("Server TCP lansat pe port " + port + "..."); // Bucla infinita while
(true) { // Asteptarea cererilor de conectare si
returnarea unui nou socket Socket
client = server.accept (); System.out.println
("Acceptata conexiunea de la: [" +
client.getInetAddress().getHostAddress() + "(" +
client.getInetAddress().getHostName() + ")" + ":" +
client.getPort() + "]...");
System.out.println ("pe portul local: " +
client.getLocalPort()); // Crearea unui fir de executie pentru
tratare client nou
firTratare = new TratareClientDeChat_v2 (client); // Lansarea firului de executie - se va
executa: firTratare.run()
firTratare.start (); } } public static void main(java.lang.String[]
args) throws IOException { if
(args.length != 1) throw
new RuntimeException ("Sintaxa: ServerDeChat_v2
<numarPort>"); new
ServerDeChat_v2 (Integer.parseInt (args[0])); } } |
Codul sursa Java pentru firul
de tratare a clientului de chat.
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 00 01 02 03 04 05 06 07 08 09 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 00 01 02 03 04 05 06 07 08 09 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 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//Source file:
TratareClientDeChat_v2.java /** * Server
chat simplu - componenta de tratare a unei conexiuni */ import java.net.*; import java.io.*; import java.util.*; import java.util.Vector; public class
TratareClientDeChat_v2 extends Thread { /** * Vector
de referinte la obiecte care trateaza clienti (ptr. inregistrare) */ private
static Vector listaClienti = new Vector (); /** * Socket
flux (TCP) */ private
Socket socket; /** * Flux de
intrare dinspre retea */ private DataInputStream
inRetea; /** * Flux de
iesire catre retea */ private
DataOutputStream outRetea; private
InfoClient client; /** *
Initializeaza obiectul (firul) care trateaza un nou client * @param socket * @throws java.io.IOException */ public TratareClientDeChat_v2(Socket
socket) throws IOException {
this.socket = socket; inRetea
= new DataInputStream (new BufferedInputStream
(socket.getInputStream ())); outRetea
= new DataOutputStream (new BufferedOutputStream
(socket.getOutputStream ())); } /** * Metoda
principala a firului de executie. * Primeste mesajele si apeleaza difuzarea
lor. */ public void run() { try { //
---------------------------------------------------------------- //
Obtinerea informatiilor de la client //
---------------------------------------------------------------- //
Citirea adresei clientului din fluxul de intrare de la client String
adresaClient = inRetea.readUTF(); //
Citirea portului clientului din fluxul de intrare de la client int
portClient = inRetea.readInt(); //
---------------------------------------------------------------------- // Obtinerea si verificarea (eventual
modificarea) numelui utilizatorului //
---------------------------------------------------------------------- //
Numele clientului String
numeClient; //
Rezultatul verificarii existentei numelui in lista
boolean existaDeja; //
Receptia numelui si eventuala cerere de modificare do { //
Citirea numelui clientului din fluxul de intrare de la client
numeClient = inRetea.readUTF();
existaDeja = false; //
Enumerare creata pornind de la lista clientilor
Enumeration enum = listaClienti.elements (); //
Cat timp mai sunt elemente in enumerare while (enum.hasMoreElements ())
{ //
Protectie la acces concurent la Vectorul clientilor
synchronized (listaClienti) {
// Obtinerea informatiilor privind clientul curent tratat
InfoClient infoClient = (InfoClient) enum.nextElement(); if (numeClient.equals(infoClient.nume))
{
existaDeja = true;
break;
}
}
} if (existaDeja) { //
Scrierea mesajului in fluxul de iesire al firului curent
outRetea.writeUTF("Numele a fost deja alocat"); } else
{ //
Scrierea mesajului in fluxul de iesire al firului curent
outRetea.writeUTF("Client inregistrat"); } //
Fortarea trimiterii
outRetea.flush(); } while (existaDeja); //
------------------------------------------------------------------- //
Trimiterea listei clientilor deja existenti (catre clientul tratat) //
------------------------------------------------------------------- //
Enumerare creata pornind de la lista clientilor
Enumeration enum = listaClienti.elements (); // Cat
timp mai sunt elemente in enumerare while (enum.hasMoreElements ())
{ //
Protectie la acces concurent la Vectorul clientilor
synchronized (listaClienti) { //
Obtinerea informatiilor privind clientul curent tratat
InfoClient infoClient = (InfoClient) enum.nextElement(); //
Scrierea mesajului in fluxul de iesire al firului curent
outRetea.writeUTF("Client nou");
outRetea.writeUTF(infoClient.nume);
outRetea.writeUTF(infoClient.adresa); outRetea.writeUTF(new
Integer(infoClient.port).toString());
} } //
Fortarea trimiterii
outRetea.flush(); //
------------------------------------------------------------------- //
Anuntarea existentei clientului curent (catre ceilalti clienti) //
-------------------------------------------------------------------
System.out.println("Difuzare informatii client nou ");
difuzare("Client nou");
difuzare(numeClient);
difuzare(adresaClient);
difuzare(new Integer(portClient).toString()); //
------------------------------------------------------------------- //
Inregistrarea informatiilor clientului tratat //
------------------------------------------------------------------- //
Inregistrarea informatiilor clientului curent client
= new InfoClient(numeClient, adresaClient, portClient, this); //
Inregistrarea clientului curent in lista (de tip Vector)
listaClienti.addElement (client); //
------------------------------------------------------------------- //
Afisarea in consola a informatiilor clientului curent tratat //
-------------------------------------------------------------------
System.out.println("\nNoul client [" + numeClient + "] are adresa
[" + adresaClient + "] si portul
[" + portClient +"]"); System.out.println("Lista clientilor
actualizata:\n" +
listaClienti.toString()+"\n"); //
-------------------------------------------------------------- //
Tratarea mesajelor clientului (citirea si difuzarea mesajelor) //
-------------------------------------------------------------- //
Bucla infinita (repetare pana la inchiderea firului curent) while (true) { //
Citirea mesajului din fluxul de intrare de la client
String mesaj = inRetea.readUTF ();
System.out.println("Difuzare mesaj: " + mesaj); //
Difuzarea catre toti clientii curent inregistrati
difuzare (mesaj);
System.out.println(); } } //
-------------------------------------------------------------- //
Tratarea erorilor de conexiune //
-------------------------------------------------------------- catch (IOException ex) { // Afisare
exceptie
ex.printStackTrace ();
} //
-------------------------------------------------------------- //
Curatenie finala //
-------------------------------------------------------------- finally { //
Eliminarea clientului curent din lista (de tip Vector)
listaClienti.removeElement (client);
System.out.println("\nClient eliminat...");
System.out.println("Lista clientilor actualizata:\n" +
listaClienti.toString()+"\n"); //
------------------------------------------------------------------- //
Anuntarea eliminarii clientului curent (catre ceilalti clienti) //
-------------------------------------------------------------------
System.out.println("Difuzare informatii client eliminat ");
difuzare("Client eliminat");
difuzare(client.nume);
difuzare(client.adresa);
difuzare(new Integer(client.port).toString()); try { // Inchiderea socketului
socket.close (); } // In
cazul unei erori legata de conexiune catch (IOException ex) { //
Afisarea exceptiei
ex.printStackTrace ();
} } } /** *
Difuzeaza mesajul primit catre clienti * @param mesaj */ private static void difuzare(String mesaj)
{ //
Enumerare creata pornind de la lista clientilor
Enumeration enum = listaClienti.elements (); // Cat
timp mai sunt elemente in enumerare while (enum.hasMoreElements ())
{ //
Referinta catre firul curent initializata cu null
TratareClientDeChat_v2 firDestinatie = null; //
Protectie la acces concurent la Vectorul clientilor
synchronized (listaClienti) { //
Obtinerea informatiilor privind clientul curent
InfoClient infoClient = (InfoClient) enum.nextElement();
System.out.print(" - catre: " + infoClient.toString()); //
Obtinerea referintei catre firul curent
firDestinatie = (TratareClientDeChat_v2) infoClient.fir; //
Daca referinta e valida if (firDestinatie != null) { try
{
// Protectie la acces concurent la fluxul de iesire
synchronized (firDestinatie.outRetea) {
// Scrierea mesajului in fluxul de iesire al firului curent
firDestinatie.outRetea.writeUTF (mesaj);
}
// Fortarea trimiterii mesajului
firDestinatie.outRetea.flush (); } //
In cazul unei erori legata de conexiune catch (IOException ex) {
// Inchiderea firului curent
listaClienti.remove(infoClient);
firDestinatie = null; }
} } } } } class
InfoClient { String nume; String adresa; int port; Thread fir; /** * @param
nume * @param
adresa * @param
port * @param
fir */ public InfoClient(String nume, String
adresa, int port, Thread fir) {
this.nume = nume; this.adresa
= adresa;
this.port = port; this.fir
= fir; } /** * @return
java.lang.String */ public String toString() { return
fir.toString() + "(" + nume + "/" + adresa +
":" + port + ")\n";
} /** * @return
boolean */ public boolean equals(Object obj) { if ((obj != null) && (obj
instanceof InfoClient)) {
InfoClient celalaltClient = (InfoClient)obj; return
((this.nume.equals(celalaltClient.nume)) &&
(this.adresa.equals(celalaltClient.adresa)) &&
(this.port == celalaltClient.port)); } return
false; } } |