0% au considerat acest document util (0 voturi)
314 vizualizări53 pagini

Programarea Aplicatiilor de Tip Client-Server in Limbajul Java

Licenta sustinuta de Andrei Pietrusel in Iunie 2013 la Facultatea de Informatica din cadrul Universitatii Bucuresti, la finalul cursurilor specializarii Informatica

Încărcat de

Andrei Pietrusel
Drepturi de autor
© © All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca PDF, TXT sau citiți online pe Scribd
0% au considerat acest document util (0 voturi)
314 vizualizări53 pagini

Programarea Aplicatiilor de Tip Client-Server in Limbajul Java

Licenta sustinuta de Andrei Pietrusel in Iunie 2013 la Facultatea de Informatica din cadrul Universitatii Bucuresti, la finalul cursurilor specializarii Informatica

Încărcat de

Andrei Pietrusel
Drepturi de autor
© © All Rights Reserved
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca PDF, TXT sau citiți online pe Scribd
Sunteți pe pagina 1/ 53

UNIVERSITATEA DIN BUCURETI

Facultatea de Matematic i Informatic


Specializarea Informatic

LUCRARE DE LICEN

Conductor tiinific:
Conf. dr. Baranga Andrei

Absolvent:
Pietruel Andrei

Bucureti
Iunie 2013

UNIVERSITATEA DIN BUCURETI


Facultatea de Matematic i Informatic
Specializarea Informatic

Programarea aplicaiilor de tip


client-server n limbajul Java

Conductor tiinific:
Conf. dr. Baranga Andrei

Absolvent:
Pietruel Andrei

Bucureti
Iunie 2013

Cuprins
1. Limbajul Java
1.1. Introducere
1.2. Istoric
1.3. Caracteristici
1.3.1. Orientarea pe obiecte
1.3.2. Independena de platform
1.3.3. Colectarea reziduurilor de memorie
1.4. Interfee grafice cu Swing

4
4
4
5
5
6
8
9

2. Aplicaii de tip client-server


2.1. Arhitectura unei aplicaii client-server
2.2. Reele i protocoale de reea
2.3. Servere. Consideraii legate de securitate i performan
2.4. Facilitile limbajului Java pentru crearea unei aplicaii de tip
client-server

13
13
15
16

3. Aplicaie practic server i client de chat text i audio


3.1. Prezentare general
3.2. Descrierea pachetelor de clase din sursa serverului
3.2.1. Privire de ansamblu
3.2.2. Pachetul ApplicationServer
3.2.3. Pachetul ApplicationServer.Voice
3.2.4. Pachetul ApplicationServer.Frames
3.3. Descrierea pachetelor de clase din sursa clientului
3.3.1. Privire de ansamblu
3.3.2. Pachetul ApplicationClient
3.3.3. Pachetul ApplicationClient.Voice
3.3.4. Pachetul ApplicationClient.Frames. Ghid de utilizare a
aplicaiei client

22
22
23
23
24
32
36
36
36
37
42

4. Concluzii

52

5. Bibliografie

53

18

47

Limbajul Java

1. Limbajul Java
1.1. Introducere
Java este un limbaj de programare orientat pe obiect al crui design a avut n
minte ca oricare dependene hardware n implementarea programelor s fie minime.
Principiul pe care se bazeaz este acela de a scrie cod o singur dat iar acesta s
poat rula dup compilare pe o multitudine de dispozitive. Aplicaiile Java sunt de
regul compilate n cod de maina virtual (bytecode) i anume fiiere .class care pot
rula pe orice maina virtual Java (JVM), indiferent de arhitectura computerului n
cauz.
Java este, n prezent, unul dintre cele mai populare limbaje de programare, folosit n
special pentru aplicaii web client-server, estimnd numrul de programatori care l
folosesc la 11 milioane.
Java a fost creat de la James Gosling la compania Sun Microsystems (care mai
trziu a devenit parte a Oracle Corporation). Limbajul a fost scos pe pia de Sun
Microsystems n 1995 ca parte component principal a platformei Java. Limbajul i
deriva n mod semnificativ sintaxa din C i C++, dar are mai puine faciliti low-level
dect oricare dintre ele.

1.2. Istoric
nceputurile limbajului Java se regsesc ntr-un proiect al lui James Gosling
numit Oak n Iunie 1991. Ceea ce Gosling voia s creeze era o main virtual i un
limbaj de programare care s aib sintax asemntoare C-ului dar cu o mai mare
simplitate i uniformitate dect C/C++. Prima implementare public a proiectului a
fost Java 1.0 n 1995. Promisiunea fcut de Sun Microsystems n ceea ce privete
noul produs al lor a fost rezumat la urmtorul slogan: Write Once, Run Anywhere,
referindu-se la faptul c un program scris n Java poate rula pe orice sistem de calcul
popular. Creaia lui Gosling se dovedise performant din punct de vedere a securitii
informaionale, iar n aceast privin maina virtual Java oferea opiunea de acces
limitat la reea i fiiere. Nu dupa mult timp de la momentul punerii pe pia a Java
1.0, browserele Web populare la vremea respectiv au incorporat maina virtual
Java n configuraiile lor, dnd natere Applet-urilor. Noi versiuni pentru platforme
4

Limbajul Java
mari i mici (J2EE i J2ME) au fost curnd create cu prilejul scoaterii pe pia a Java 2.
n 1997, Sun a adoptat standardele ISO/IEC JTC1 iar apoi cele ale Ecma
International pentru a formaliza Java, dar mai trziu s-a abtut de la proces. Sun face
ca majoritatea implementrilor platformei Java s fie disponibile publicului larg n
mod gratuit, majoritatea profitului firmei fiind obinut din produse specializate
precum Java Enterprise System. Sun deosebete dou categorii distincte de
implementri a platformei Java: Development Kit (JDK), care permite creerea de
aplicaii folosind limbajul Java, i Runtime Environment (JRE) care este necesar rulrii
aplicaiilor Java dar nu permite dezvoltarea acestora, compilatorul nefiind inclus.

1.3. Caracteristici
In crearea limbajului Java au existat cinci principii:
1. Trebuie s foloseasc metodologia programrii orientat pe obiecte
2. Trebuie s permit rularea pe mai multe sisteme de operare a unui program
creat folosind limbajul
3. Trebuie s conin suport integrat pentru folosirea reelelor de calculatoare
4. Trebuie s fie conceput astfel nct executarea de cod de la surse externe s
fie sigur
5. Trebuie s fie uor de folosit, selectnd ceea ce era considerat bun de la alte
limbaje orientate pe obiect
Relativ la principiile pe care s-a bazat crearea limbajului Java, voi expune n cele
ce urmeaz principalele caracteristici ce l definesc.

1.3.1. Orientarea pe obiecte

Prima caracteristic, orientarea pe obiect, se refer la o metod de


programare i design a unui limbaj. Chiar dac sunt multiple interpretri ale
orientrii pe obiect, o idee central a acestui concept este aceea de a crea
software ale crui tipuri de date diverse s fie combinate mpreun cu operaiile lor
relevante. Aadar, datele i codul sunt combinate ntru entiti numite obiecte. Un
obiect poate fi gndit ca o grmad de aciuni (cod) i stri (date). Principiul este
acela de a separa lucrurile care se schimb de lucrurile care rmn la fel. De multe
ori, o schimbare a unei structuri de date necesit schimbari ale codului care opereaz
5

Limbajul Java
pe acele date sau invers. Separarea in obiecte coerente ofer o fundaie mai stabil
pentru design-ul unui sistem software. Scopul este acela de a face marile proiecte
software mai usor de ntreinut, mbuntind astfel calitatea i reducnd numrul de
proiecte euate.
Un alt principiu central al programrii orientate pe obiecte este acela de a
dezvolta obiecte mai generice, astfel nct codul s poate fi refolosit n multiple
proiecte. Un obiect generic, ca de exemplu client ar trebui s aib aproximativ
acelai set de comportamente (aciuni) n proiecte diferite, n special dac aceste
proiecte au n comun un nivel fundamental al logicii de programare cum se ntmpl
de obicei n companiile mari. n acest sens, obiectele pot fi vzute precum
componente refolosibile, ajutnd industria software s creeze proiecte n mare
msur din piese existente care sunt extensiv testate, n acest mod reducnd masiv
timpul necesar n dezvoltarea acestora. Reutilizabilitatea soft-urilor a avut rezultate
mprite, dar preponderent pozitive. Principalele dificulti ale acestei abordri n
proiectarea aplicaiilor sunt design-ul unor obiecte cu adevrat generice i lipsa unei
metodologii de comunicare masiv ntre dezvoltatorii de software care s ofere
oportuniti de cod reutilizabil.

1.3.2. Independena de platform


A doua caracteristic, independena de platform se refer la faptul c
programele scrise n Java trebuie s ruleze similar pe hardware diferit. Un
programator ar trebui s scrie cod o singur dat iar acesta s ruleze oriunde.
Acest lucru este satisfcut de majoritatea compilatoarelor, prin compilarea
codului Java n bytecode (instruciuni maina simplificate specifice platformei Java).
Codul astfel obtinut este apoi rulat pe o masina virtual Java, un program scris n cod
nativ corespunztor hardware-ului gazd, interpretnd i executnd instruciunile din
bytecode. n continuare, librrii standardizate sunt utilizate pentru a permite acces
ctre facilitile sistemului gazd (cum ar fi, grafica, threadurile i reeaua).
De precizat este faptul c, dei exist un stadiu explicit al compilrii, la un
anumit punct, bytecode-ul Java este interpretat sau convertit n cod main nativ de
ctre compilatorul Just-in-time (JIT). Compilarea Just-in-time, numit i translatare
dinamic este o metod de optimizare a performanei la rulare a programelor pentru
maini virtuale bazate pe bytecode. Pentru c bytecode-ul este interpretat, este
executat mai ncet dect codul main compilat. Acest lucru poate fi remediat, pe de6

Limbajul Java
o parte, prin compilarea nainte de execuie a bytecode-ului n cod main, lucru care
ar face totui ca faza de ncrcare a programului s dureze mai mult. O alt metod
mai eficient este stocarea n memorie ca bytecode a programului i compilarea
preliminar a segmentul de cod care trebuie rulat curent, mbuntind astfel viteza
de rulare. Compilatorul JIT inclus n maina virtual Java folosete o metod hibrid
ntre cele amintite, translatarea ntmplndu-se n mod continuu, asemeni
interpretoarelor, dar innd totui un cache al codului translatat pentru a minimiza
degradarea performanei. Pe de alt parte, aceasta soluie de optimizare ofer i alte
avantaje precum suportul pentru date late-bound i abilitatea de a garanta
integritatea i securitatea programului. Compilarea JIT a fost creat dup dou idei
existente deja i anume compilarea bytecode-ului i compilarea dinamic.
Rezumnd, principiul compilrii JIT pentru Java este conversia la rulare a bytecodeului corespunztor mainii virtuale Java n machine code corespunztor sistemului
hardware gazd.
Exist totui implementri de compilatoare Java care compileaz n cod obiect
nativ, cum ar fi GCJ, scpnd de pasul intermediar al bytecode-ului, dar produsul final
al acestor compilatoare poate fi rulat doar pe o singur arhitectur.
Licena lui Sun pentru Java insista ca toate implementrile ale mainii virtuale
trebuie s fie compatibile. Acest lucru a cauzat o disput n instan cu Microsoft,
atunci cnd Sun a aclamat c implementarea fcut de Microsoft nu suport
interfeele RMI i JNI i adaug faciliti dependente de o platform (Windows). Ca
rspuns la aceast acuzare, Microsoft nu a mai distribuit Java ca parte component a
sistemelor de operare Windows, iar urmatoarele versiuni ale Internet Explorer nu
mai suportau applet-uri Java fr un plugin third-party. Totui, Sun i alte companii
au fcut disponibile implementri gratuite ale runtime-ului Java (JRE) pentru acestea
i pentru noile versiuni de Windows.
Primele implementri ale limbajului foloseau o main virtual interpretat
pentru a obine portabilitatea. Acestea produceau programe care rulau mai ncet
dect programele compilate n executabile native scrise n C sau C++. Din acest
motiv, limbajului Java i s-a atribuit o reputaie proast din punct de vedere al
performanei. Cele mai recente implementri ale JVM, n schimb, produc programe
care ruleaz n mod semnificativ mai repede dect nainte, folosind diverse tehnici.
Prima tehnic este s compileze direct n cod nativ ca un compilator tradiional,
srind peste transformarea n bytecode n ntregime. Acest lucru asigur
performan superioar dar vine cu preul portabiliii. O alt tehnic este
compilarea JIT explicat anterior. Alternativa la cele doua tehnici, folosit pentru
7

Limbajul Java
creterea vitezei de execuie este recompilarea dinamic. Aceasta presupune ca
maina virtual s analizeze comportamentul unui program rulat i s recompileze i
optimizeze selectiv pri critice ale acestuia. Recompilarea dinamic poate oferi
optimizri mai mari chiar dect compilarea static (tradiional) specific limbajelor
native, deoarece compilatorul dinamic i poate baza optimizrile pe anumite
informaii accesibile doar n timpul rulrii programului cum ar fi mediul sau clasele
ncrcate. mpreun, compilarea Just-in-time i recompilarea dinamic ofer
programelor Java avantajul vitezelor foarte apropiate de cele ale codului nativ, fr a
pierde portabilitatea.
Portabilitatea este o dificultate tehnic major iar succesul lui Java n aceast
arie a avut urcuri i coboruri de-a lungul timpului. Chiar dac a scrie programe pe
platforma Java care s ruleze n mod consistent pe multiple platforme gazd este
ntr-adevr posibil, exist totui un numr mare de sisteme pe care programele Java
ruleaz cu minimale erori i inconsistene.
Aplicaiile Java independente de platform, totui, cum ar fi cele server-side ca
serviciile Web, servleii, Enterprise JavaBeans i sistemele nglobate bazate pe OSGi
ce folosesc Java se bucur de un succes considerabil.

1.3.3. Colectarea reziduurilor de memorie


O idee din spatele management-ului automat al memoriei folosit de Java este
concepia c programatorii ar trebui s fie scutii de munca greoaie a alocrii i
dealocrii manuale a memoriei. n unele limbaje, programatorul este nevoit s aloce
memorie pentru a crea obiecte stocate pe heap i este responsabil, mai trziu s
dealoce acea memorie pentru a terge respectivele obiecte. Dac acesta uit s
dealoce memoria sau scrie cod care eueaz n a face acest lucru n timp util, o
scurgere de memorie (memory leak) poate aprea, caz n care programul va consuma
o mare parte din memoria disponibil sistemului. n plus, dac o regiune de memorie
este dealocat de dou ori, programul poate deveni instabil i ceda.
n Java, aceast potenial problem este evitat prin colectarea automat a
reziduurilor de memorie (automatic garbage collection). Programatorul determin
cnd sunt create obiectele iar maina virtual Java este responsabil s se ocupe cu
management-ul duratei de existen n memorie a acestor obiecte. Programul sau
alte obiecte pot contacta un obiect innd o referin la acesta (care, din punct de
vedere low-level este echivalent cu o adres de pe heap). Cnd nu mai exist
8

Limbajul Java
referine la un anumit obiect, colectorul de reziduuri Java l terge n mod automat,
golind memoria i prevenind, astfel, o scurgere. Scurgeri de memorie pot nc
aprea, totui, dac programatorul ine referine la obiecte care nu mai sunt
necesare, ntr-un cuvnt scurgerile pot nc aprea dar la un nivel conceptual mai
nalt.
Folosirea colectrii rezuduurilor de memorie poate afecta i anumite
paradigme de programare. De exemplu, dac programatorul estimeaz costul
alocrii/recolectrii memoriei ca fiind mic, ar putea s aleag s construiasc obiecte
ntr-un mod mai liber n loc s le preiniializeze, innd referine la ele i refolosindule. Avnd n vedere micul cost al uoarei scderi a performanei (de exemplu anumite
structuri repetitive folosite n creerea unor obiecte mari, complexe), aceasta metod
faciliteaz izolarea thread-urilor (nu mai este nevoie de a sincroniza multiple threaduri, fiecare dintre acestea lucrnd pe instane de obiecte diferite).
Fcnd o comparaie ntre Java i C++ n ceea ce privete managementul
automat al memoriei, este posibil n C++ a implementa o funcionalitate similar cu
ceea ce ofer Java dar acest lucru necesit timp i complexitate suplimentar n
aplicaie. De exemplu, un model pentru dealocarea automat a memoriei poate fi
scris pentru anumite clase n C++ pentru a mbunti viteza i a limita fragmentarea
memoriei n mod considerabil. n Java, colectarea reziduurilor este integrat i virtual
invizibil programatorului. Din aceast cauz, dezvoltatorii de software nu cunosc
momentul exact al dealocrii automate a memoriei, acesta nefiind corelat cu aciuni
explicit scrise n cod. n funcie de aplicaia care se dorete a fi creat, acest lucru
poate fi ori benefic, ori un dezavantaj: programatorul este eliberat de povara
cerinelor low-level dar n acelai timp pierde opiunea de a scrie cod de nivel sczut.

1.4. Interfee grafice cu Swing


Swing este principalul set de instrumente pentru design-ul de interfee grafice
n Java. Este parte a Java Foundation Classes (JFC), un API pentru furnizarea
elementelor de grafic pentru programe scrise n Java. Swing a fost creat pentru a
oferi un set mai avansat de componente pentru interfee grafice dect vechiul
Abstract Window Toolkit (AWT). Swing combin stilul grafic i funcionalitatea unor
controale de interfa de pe platforme diferite. Totui, controalele Swing i afirm
un stil propriu, i datorit platformei Java, acestea vor fi afiate identic din punct de
vedere grafic i vor avea aceeai funcionalitate indiferent de sistemul gazd.
Componentele din Swing sunt mult mai puternice i mai flexibile dect cele AWT. n
9

Limbajul Java
afar de componente ades ntlnite precum butoane, csue bifabile i etichete,
Swing mai ofer i elemente de interfa mai avansate precum panouri cu taburi,
tabele, liste derulabile, etc. O alt diferen major ntre Swing i AWT este faptul c
Swing este n intregime scris n Java, prin urmare toate componentele sale sunt
independente de platform, termenul lightweight fiind folosit pentru a le descrie
aceasta calitate.
Dac dorim s facem un scurt istoric al Swing, putem considera ca punct de
origine Internet Foundation Classes (IFC), o librrie grafic pentru Java dezvoltat
original de Netscape Communication Corporation i fcut public pentru prima oar
pe 16 decembrie 1996. Pe 2 aprilie 1997, Sun Microsystems i Netscape
Communications Corporation au anuntat intenia lor de a ncorpora IFC cu alte
tehnologii din Java Foundation Classes. Java Foundation Classes au fost mai tarziu
redenumite Swing.
Swing a introdus un mecanism care permitea afirii grafice i funcionalitii
fiecrei componente de interfa s fie alterate fr a face schimbri substaniale n
logica aplicaiei. Unul din punctele cheie care a stat la baza dezvoltrii Swing a fost
caracterul de plugin al acestuia, permind rapida fuzionare a codului logicii aplicaiei
cu cel al interfeei grafice. Printre avantajele noi aduse de Swing se numar desigur i
portabilitatea amintit anterior, componentele de interfa putnd acum s emuleze
stilul grafic specific interfeei native a sistemului, neabandonnd ns avantajele
independenei de platform. Swing a fost introdus ca parte a Java Standard Edition
ncepnd cu versiunea 1.2.
Clasele i componentele Swing sunt coninute n pachetele din ierarhia
javax.swing. Toate componentele deriv din clasa javax.swing.Jcomponent. Obiectele
Swing arunc evenimentele (events) n mod asincron, au proprieti i rspund la un
set documentat de metode specifice fiecrei componente. Toate componentele
Swing sunt Java Beans n conformitate cu specificaiile arhitecturii Java Beans
Component ce promoveaz codul reutilizabil.
Lund n considerare modelul de randare al interfeei Swing, controlul fin
asupra randrii unei componente este posibil. Reprezentarea vizual a unei
componente Swing este o compunere de elemente dintr-un set standard ce conine
rame, identri, decoraii i alte proprieti. n mod tipic, programatorii vor modifica
din cod o astfel de component, definind rame, culori, fundale i opaciti n funcie
de stilul vizual preferat. Componenta apoi va folosi aceste proprieti la randare.
Totui, este posibil a crea controale GUI cu o reprezentare vizual foarte
personalizat.
10

Limbajul Java
Swing se bazeaz pregnant pe mecanisme disponibile n timpul execuiei
programului (runtime) i astfel permite rspunderea i adaptarea rapid la schimbri
fundamentale de setri n timpul rulrii. De exemplu, o aplicaie bazat pe Swing are
capacitatea de a-i schimba instant interfaa grafic fr a interfera cu logica
aplicaiei. Acest lucru este util n cazul programelor care ofer interfee alternative
utilizatorilor, numite de obicei skins sau n cazul programelor ce necesit trecerea
de la un meniu la altul n cadrul aceleiai ferestre.
Nivelul de flexibilitate al Swing este reflectat de abilitatea sa inerent de a
trece peste conveniile controalelor grafice ale sistemului de operare nativ pentru a
se afia. Swing i randeaz controalele cu ajutorul unor API-uri Java 2D, n loc s
apeleze setul de instrumente pentru interfaa grafic a platformei native. Aadar, o
component Swing nu are un echivalent corespunztor sistemului de operare al
hardware-ului gazd i este liber s se afieze n orice mod permis de API-urile de
randare amintite. Totui, la baz, fiecare component Swing are un container AWT
deoarece Jcomponent al lui Swing extinde Container al lui AWT. Acest lucru permite
Swing s se foloseasc de elemente cruciale ale sistemului de operare nativ i anume
interaciunile cu utilizatorul (apsri de taste sau micri ale mouse-ului. Swing doar
i transpune semantica independent de platform peste componentele native ale
sistemului gazd. De exemplu, fiecare component Swing este randat de
dispozitivul grafic (placa video) ca rspuns al apelului metodei component.paint(),
care e definit n (AWT) Container. Dar spre deosebire de componentele AWT, care
delegau afiarea lor sistemului de operare gazd, componentele Swing sunt
responsabile de propria lor randare. Aceast decuplare nu este doar vizual ci este
extins la managementul unei semantici de aplicaie independent de sistemul de
operare n cadrul ierarhiei de componente din pachetele din javax.swing.
Librria Swing se folosete mult de modelul de design sofware Model-ViewController (MVC) care n mod conceptual decupleaz datele vizualizate de interfaa
grafic n care sunt afiate. De aceea, cele mai multe dintre componentele Swing au
asociate modele (care sunt specificate n cod Java prin interfee), iar programatorii
pot folosi pentru acestea o multitudine de implementri implicite sau pot furniza
unele create de ei. Framework-ul Swing ofer implementri implicite de modele de
interfa pentru toate componentele sale concrete. Folosirea tipic a Swing nu
necesit crearea de modele personalizate deoarece framework-ul ofer un set de
implementri implicite care sunt n mod transparent asociate cu clasa derivat din
JComponent corespunztoare componentei n cauz. n general, doar componentele
complexe precum tabelele, arborii sau uneori listele au nevoie de modele
personalizate care s corespund cu structurile de date specifice aplicaiei.
11

Limbajul Java
n mod tipic, obiectele model ale componentelor Swing sunt responsabile cu
oferirea unei interfee concise care s defineasc event-urile aruncate i a unor
proprieti accesibile pentru modelul de date conceptual, pentru a putea fi folosite
de JComponent-ul asociat. innd cont c MVC este n principiu bazat pe relaii
discrete ntre obiecte ce se doresc a colabora, un obiect model ofer facilitile
necesare n programare pentru a ataa un event listener obiectului corespunztor
modelului de date. De obicei, aceste event-uri sunt centrate pe model (de exemplu
un event pentru inserarea unui rnd ntr-un model tabel) i sunt mapate de
specializarea JComponent ntr-un eveniment concret pentru componenta vizual
(GUI). De exemplu JTable are un model numit TableModel care descrie o interfa
pentru accesarea datelor dintr-un tabel. O implementare implicit pentru acest lucru
opereaz pe un tablou bidimensional.
Componenta vizualizare (view) a unei componente Swing este obiectul folosit
pentru a afia grafic controlul GUI conceptual. O distincie a Swing este, dup cum s-a
afirmat anterior, folosirea randrii din cod a controalelor (n comparaie cu AWT care
folosea controalele grafice ale sistemului de operare nativ). nainte de Java 6 Update
10, aceast deosebire era o surs de complicaii cnd se foloseau n aceai aplicaie
att controale Swing, ct i controale AWT.
n ceea ce privete compunerea elementelor vizuale i managementul
acestora, Swing ofer layout-uri relative, care se bazeaz pe relaiile dintre poziiile
componentelor n contrast cu layout-uri absolute care specific exact locaiile i
dimensiunile componentelor. Aceast tendin ctre ordonarea vizual fluid i
are originile n dezvoltarea mediului de operare al applet-urilor care a condus ulterior
la design-ul setului original de instrumente pentru interfee grafice Java GUI Toolkit.
O observaie interesant este i similaritatea acestui mod de organizarea a afirii
elementelor grafice n Java Swing cu cel folosit n randarea coninutului HTML n
browsere Web.

12

Aplicaii de tip client-server

2. Aplicaii de tip client-server


2.1. Arhitectura unei aplicaii client-server
Pentru a putea face o prezentare detaliat a aplicaiei de chat concepute n
proiectul curent, este necesar expunerea unor consideraii generale despre
fundamentele conceptuale folosite n crearea unei aplicaii de tip client-server,
restrngnd apoi generalitatea la mijloacele oferite de Java pentru realizarea unei
astfel de aplicaii.
Arhitectura software de tip client-server este o tehnic folosit n
programarea reelelor de calculatoare dezvoltat de firma Xerox PARC n anii 70. La
ora actual aceasta este folosit intensiv n reele de calculatoare, n email, World
Wide Web i n imprimarea pe reea, resurse indispensabile lumii moderne.
Modelul client-server atribuie dou roluri calculatoarelor dintr-o reea: client
i server. Un server este un sistem informatic care i imparte n mod selectiv
resursele iar un client este un computer sau o aplicaie care iniiaz contactul cu
serverul cu scopul de a folosi o resurs de pe acesta. Exemplele de resurse cuprind
date, procesoare, imprimante, dispozitive de stocare a informaiilor, etc. Acest tip de
partajare a resurselor unui sistem informatic se numete time-sharing pentru c
permite multiplilor utilizatori s foloseasc un calculator (n acest caz, serverul) n
mod simultan. Pentru c un calculator execut un numr limitat de cerine ntr-un
anumit interval de timp, un sistem de partajare inteligent n funcie de prioriti
trebuie creat n majoritatea implementrilor unui model client-server.
Clienii i serverele fac schimb de mesaje ntr-o repetiie de cereri i
rspunsuri: clientul trimite o cerere i serverul ntoarce un rspuns. Pentru a
comunica, calculatoarele trebuie s aib n comun un mijloc de limbaj i trebuie s se
supun unor reguli ce definesc ce mesaje de cerere sau ofert se pot primi i trimite.
Limbajul i regulile pentru mesaje sunt definite ntr-un protocol de comunicare. Un
protocol de comunicare este un sistem de formatari pentru mesaje digitale si de
reguli pentru schimbul acestor mesaje folosit n totalitatea comunicaiilor dintr-o
13

Aplicaii de tip client-server


reea de sisteme informatice. Un protocol poate include semnalri, autentificri,
detecie de erori i posibilitatea corectrii erorilor. Definirea unui protocol de
comunicare presupune sintax, semantic i sincronizarea comunicrii.
Comportamentul specificat este de obicei independent de viitoare implementri ale
unei aplicaii client-server care s l foloseasc. Sistemele care comunic folosesc
formate bine definite pentru a face schimb de mesaje. Fiecare mesaj are o semantic
exact identic att pentru emitor ct i pentru receptor pentru asigurarea
interpretrii corecte a mesajelor de ambii comunicani. Ca o paralel cu limbajele de
programare care asigur o cale de comunicare ntre programator i computer, un
protocol de comunicare poate fi privit n mod similiar, relaia fiind n acest caz intre
dou sisteme informatice.
Atunci cnd un computer este un client, un server, sau ambele, acesta poate
satisface funcii multiple. De exemplu, un singur calculator, poate rula un server web,
unul de fiiere i unul de mail n acelai timp pentru a servi resurse diferite clienilor
care fac cereri de o diversitate sporit. Software-ul client poate comunica
deasemenea cu un software server de pe acelai calculator. Comunicarea ntre
servere este posibil, fiind necesar n anumite situaii pentru a sincroniza date i
este numit comunicare inter-server sau server-to-server.
ntr-o arhitectur client-server, serverul este un sistem centralizat. Cu ct
exist mai muli clieni simultani, cu att de mai multe resurse are nevoie serverul.
ntr-o reea peer-to-peer, unde informaiile nu sunt centralizate, dou sau mai multe
calculatoare i partajeaz resursele pentru a comunica ntr-o manier decentralizat.
Participanii la comunicarea datelor i transferul resurselor ntr-un astfel de scenariu
se situeaz pe acelai nivel de privilegii ntruct nu exist o ierarhie a reelei. Ca un
efect advers, calculatoarele care au o putere de manipulare a datelor sczut vor
cauza redundan ntregului ansamblu de sisteme din reea n cazul n care resurse
aflate pe acestea sunt accesate. ntruct majoritatea participanilor ntr-un sistem de
reea peer-to-peer sunt calculatoare personale, resursele acestora nu pot fi accesate
n mod constant, fiind improbabil ca sistemele acestor utilizatori s fie online
permanent. Totui, atta timp ct cel puin unul dintre nodurile reelei este online i
deine informaia necesar la un moment dat, resursa respectiv rmne disponibil.
Analiznd diferenele prezentate ntre o arhitectur de reea client-server i una
peer-to-peer, observm avanajele primei, printre care: accesul permanent la resurse,
eliminarea redundanelor legate de puterea de manipulare a datelor (folosind
hardware i software specializat) precum i controlul avansat al partajrii resurselor
i al prioritilor.
14

Aplicaii de tip client-server

2.2. Reele i protocoale de reea


Pentru a ajunge s discutm despre aplicaii care folosesc o arhitectur de tip
client-server, trebuie mai nti s cunoatem noiunile de reea i protocol de reea.
O reea este un ansamblu de calculatoare i periferice (imprimante,
modemuri, routere, etc.) conectate ntre ele. Reelele, n funcie de amplitudinea lor
se mpart n reele LAN (Local Area Network) i reele WAN (Wide Area Network) .
Reelele LAN sunt folosite n general pentru partajare de resurse ntre nodurile
ce compun reeaua. De obicei, interconectarea calculatoarelor i perifericelor ce
compun o reea LAN se realizeaz prin cablu, dar o alternativ din ce n ce mai
popular este folosirea Wireless-ului (Wi-Fi) mai ales cnd avem un numr ridicat de
dispozitive mobile (smartphone-uri, tablete, laptopuri, etc.). Ambele soluii impun o
limit de distan de ordinul kilometrilor, n cel mai fericit dintre cazuri. ntr-o astfel
de reea, la fiecare moment dat n timp se realizeaz o singur transmitere de mesaj.
Acest tip de reea se supune unor dificulti algoritmice legate de eficiena
transmiterii datelor. Printre cele mai notabile se numra broadcasting-ul
(transmiterea unui mesaj ctre toate celelalte noduri), detectarea terminrii unei
aciuni a unui nod de care depinde alte noduri, evitarea unui deadlock n accesarea
resurselor, precum i gestionarea distribuit a fiierelor.
Reelele WAN sunt reele ce acoper arii ntinse de teren (ex. Reele care
leag regiuni metropolitane, regionale i naionale). De obicei, reele WAN
conecteaz o multitudine de reele LAN ntre ele asigurnd transmiterea de date
ntre acestea. Ratele de transmisie variaz ntre 1200bii/secund i
24Mbii/secund; totui reelele de bancomate sau cele folosite de instituii
importante pot atinge viteze mai mari de 156Mbii/secund.
Recent, odat cu proliferarea internetului de cost sczut, multe companii i
organizaii precum Cisco, Citrix sau Check Point au trecut la VPN (Virtual Private
Networks) pentru a i interconecta reelele.
Un protocol de reea definete reguli i convenii pentru comunicarea ntre
dispozitivele unei reele. Protocoalele de reea ofer mecanismele necesare
dispozitivelor unei reele pentru ca acestea s se identifice ntre ele i s se
conecteze unul la cellalt. n plus, protocoalele impun reguli care specific modul n
care datele sunt mpachetate n mesaje iar apoi trimise i primite de dispozitivele
reelei.
15

Aplicaii de tip client-server


Familia protocolului de internet (IP) conine un set al celor mai utilizate
protocoale de reea. n afara protocolului de internet (Internet Protocol IP), alte
protocoale de nivel mai nalt, precum TCP, UDP, HTTP sau FTP sunt integrate n
familia IP pentru a asigura funcionaliti adiionale. Aceste protocoale de nivel nalt
interacioneaz mai ndeaproape cu aplicaii precum browsere Web, n timp ce
protocoalele de un nivel mai sczut interacioneaz cu adaptoare de reea i alte
componente hardware.

2.3. Servere. Consideraii legate de securitate i performan


Cu beneficiile majore aduse de modelul client-server, vin i responsabiliti
suplimentare att pentru designerii aplicaiilor pentru server ct i pentru
administratorii de reea ce se vor ocupa cu metenana i securitatea acestuia.
Este de la sine neles c un simplu utilizator nu va atrage interesul unui atac
direct al hackerilor n majoritatea cazurilor. Adevratele provocri ale atacatorilor
sunt serverele, deoarece prin exploatarea eventualelor guri de securitate ale
acestora se pot obine cantiti mpresionante de date, un server, ntr-o companie
important, gestionnd informaii care vizeaz un numr imens de persoane. Din
prezentarea fcut legat de arhitectura software client-server, tim c un server
este un calculator care ruleaz un soft ce are n vedere oferirea de servicii simultane
pentru o mulime de utilizatori, numii clieni. Serviciile oferite sunt strns corelate
cu natura serverului. Ca exemplu, un server de fiiere va oferi acces la descrcarea i
ncrcarea de fiiere tuturor clienilor, unul de printare va permite folosirea comun
a imprimantelor de mai muli utilizatori, unul WEB va gzdui site-uri vizibile oricruia
cu o conexiune la internet, etc.
Dincolo de securitatea ce se impune unui calculator personal, un server,
datorit confidenialitii maxime pe care trebuie s o confere datelor cu care
lucreaz, trebuie s implementeze anumite msuri de protecie adiionale. De multe
ori, termenul de server va conduce un necunosctor de reelistic cu gndul la un
supercalculator, mult mai avansat decat cel din cas sau birou. Chiar dac, desigur
acesta este un mit, un soft server putnd s ruleze pe orice sistem cu acces la o
reea, exist o smn de adevr n toat aceast credin. Din motive de stabilitate
i securitate a datelor, marile servere au hardware specializat ce contribuie la
asigurarea faptului c acesta va rula la putere maxima 24 de ore pe zi i va putea
procesa cereri de la un numr de clieni de ordinul miilor. Dac serverul nu ar
beneficia de o asemenea putere de manipulare a datelor, unui hacker i-ar fi foarte
16

Aplicaii de tip client-server


uor s lanseze on atac denial of service (DoS) care ar bloca accesul clienilor la
resursele de pe server. Un astfel de atac, care const n suprancrcarea serverului cu
cereri triviale, poate nc reprezenta un pericol pentru buna funcionare a acestuia
atunci cnd hackerii folosesc mai multe calculatoare, proces numit distributed
denial of service (DDoS) pentru a lansa atacul. n aceste condiii, se vor folosi
anumite filtre software sau hardware care s identifice anomaliile n trafic i s taie
conexiunile posibilor hackeri. Software-ul ce ruleaz pe un server este i el foarte
bine pus la punct, un exemplu sugestiv fiind programarea atent a aplicaiilor pentru
un server de baze de date pentru a elimina riscul unui SQL Injection (tehnic de
apelare cu scopuri malicioase a unor funcii SQL prin intermediul unor simple
cmpuri de introducere date din client).
Printre elementele care sporesc securitatea i stabilitatea unui server se
numr un sistem de operare specializat n management-ul conexiunilor concurente
i gestionarea eficient a resurselor. Fie el Microsoft Windows Server 2008, Red Hat
Linux sau Mac OS X Server, acesta va avea o arhitectur minimalist n interfa dar
va implementa un mediu ideal de rulare non-stop a unei aplicaii server. Desigur,
pentru o aplicaie Java, care folosete o main virtual pentru a rula serverul,
componenta securitii i mai sporit.
i dac software-ul pentru server a fost atent conceput i nu prezint anomalii
care pot compromite securitatea sau performana acestuia, trebuie considerate i
beneficiile asupra integritii datelor oferite de componente hardware specializate
pentru un sistem server. Aadar, impactul suprem, dincolo de o bun conexiune la
internet (sau reea) asupra funcionrii unui server l are procesorul. Toi marii
productori de procesoare au lansat i produse specializate serverelor. Acestea ofer
capaciti superioare de lucru simultan cu date pentru satisfacerea cererilor
multiplilor clieni, reducnd drastic eventuale pierderi de date sau cedri ale
sistemului. n acelai registru de idei intr i memoria ECC (Error-Checking and
Correction), un tip de RAM care testeaz i corecteaz erorile n mod automat, fr
ca sistemul de operare s fie mcar ntiinat de acest lucru. n ceea ce privete
stocarea datelor, pentru a preveni pierderile care ar interveni n cazul cedrii hard
disk-ului, se implementeaz sistemul RAID (redundant array of independent disks)
care const n combinarea mai multor hard-disk-uri intr-o singur unitate logic,
fiecare dintre ele avnd cte o copie independenta a datelor, ce poate fi folosita
pentru a le accesa. n cazul cedrii unuia dintre ele, acesta va putea fi nlocuit fr ca
mcar s fie necesar oprirea serverului, urmnd s i reconstruiasc copia datelor
n mod automat. i cum o pan de curent ar avea consecine majore asupra
17

Aplicaii de tip client-server


integritii informaiilor manipulate de server, se folosesc multiple surse de
electricitate care asigur c serverul nu va cdea ntr-o astfel de situaie.

2.4. Facilitile limbajului Java pentru crearea unei aplicaii


de tip client-server
Trecnd de la generala descriere a modelului client-server la concretizarea
ideilor expuse prin facilitile oferite de Java, ne propunem expunerea principalelor
clase i metode folosite pentru crearea unei aplicaii care s implementeze
arhitectura descris.
Java ofer packetul java.net, care este construit pentru a oferi clase care
implementeaz funcionalitile uzuale necesare n crearea unei aplicaii care
folosete modelul client-server. n continuare vor fi prezentate cele mai importante
dintre acestea, exemplificnd, dup caz. Expunerea acestora se va identifica cu
fundamentele teoretice ale aplicaiei practice create n aceast lucrare.
Socketurile sunt obiecte utilizate n transmiterea de date prin protocolul
TCP/IP. Acestea trebuiesc create att pe server ct i pe client. n Java, tipul de date
care le implementeaz este definit de clasa Socket n cazul clientului, i ServerSocket
n cazul serverului, ambele clase fiind din pachetul java.net. Pentru a comunica
mesaje prin socketuri, acestora li se va ataa cte un flux de intrare i unul de ieire.
Exemplificnd, n urmtorul bloc de cod se creaz un socket pentru un client unde
variabila address este considerat a fi adresa IP a serverului iar nrport este portul ales
pentru comunicarea mesajelor.
Socket cs = null;
InputStream is = null;
OutputStream os = null;
try {
cs = new Socket(adresa,nrport);
is = cs.getInputStream(); os = cs.getOutputStream();
}
catch(UnknownHostException e) { ... }
catch(IOException e) { ... }

18

Aplicaii de tip client-server


Dup cum se observ, socketului i sunt ataate fluxul os de ieire ce va fi
folosit pentru a transmite date serverului, precum i fluxul is ce va fi folosit pentru
recepionarea datelor transmise de server. n funcie de logica programului ce se
dorete a fi creat, fluxurile vor fi nzestrate cu facilitile de transmitere a datelor
primite.
Pentru crearea unui socket pentru server se procedeaz ca n exemplul
urmtor:
ServerSocket ss = null; Socket cs = null;
try {
ss = new ServerSocket(nrport);
// System.out.println("Serverul a pornit");
}
catch(IOException e) { ... }
InputStream is = null; OutputStream os = null;
try {
cs = ss.accept();
is = cs.getInputStream();
os = cs.getOutputStream();
}
catch(UnknownHostException e) { ... }
catch(IOException e) { ... }

Se observ c pentru un server, specificarea adresei IP nu este necesar, ci


doar a cea ce portului care trebuie s fie acelai cu cea care va fi precizat de ctre
client pentru a se conecta la server.
Modul de funcionare a metodei accept este urmtorul: se ateapt ca un
client s ncerce s se conecteze la server pe portul precizat, iar n momentul n care
acest lucru se ntmpl, metoda va crea i va ntoarce un obiect de tip Socket (client)
denumit in exemplu cs. Acestui socket i se ataeaz dou fluxuri, unul de intrare i
unul de ieire, acestea implementnd, la fel ca i n cazul clientului, facilitile de
transmitere a mesajelor.
Este important ca socket-urile s fie nchise prin metoda close n momentul n
care dorim terminarea conexiunilor ntre server i clieni pentru ca porturile folosite
s fie eliberate iar fluxurile de intrare i ieire s fie inchise odata cu ele.
19

Aplicaii de tip client-server


Pentru a nelege pe deplin funcionalitile metodelor din clasele Socket i
ServerSocket voi lista n cele ce urmeaz prototipurile acestora nsoite de descriere.
Pentru clasa Socket, ce definete un socket de client metode notabile sunt:
constructorul care creeaz un socket i l conecteaz la portul port al
serverului cu numele simbolic host
Socket(String host, int port)
throws IOException,UnknownHostException

constructorul care creeaz un socket i l conecteaz la portul port al


serverului cu adresa URL host
Socket(InetAddress host, int port)
throws IOException

metoda getInputStream care ntoarce un flux de intrare pentru obiectul de


tip Socket curent
InputStream getInputStream()
throws IOException

metoda getOutputStream care ntoarce un flux de ieire pentru obiectul de


tip Socket
InputStream getOuputStream()

throws IOException

metoda close care nchide socketul curent


void close()
throws IOException

20

Aplicaii de tip client-server

Pentru clasa Server Socket, ce definete un socket de server metode notabile


sunt:
constructorul care creeaz un socket de tip server ce folosete portul port
ServerSocket(int port)
throws IOException

metoda accept care ateapt o conexiune a unui client la socket-ul server


reprezentat de obiectul curent i dup ce aceasta este realizat, creaz i
ntoarce un obiect Socket de tip client
Socket accept()
throws IOException

metoda close care nchide socket-ul curent


void close()
throws IOException

21

Aplicaie practic server i client de chat text i audio

3. Aplicaie practic server i client de chat text i


audio
3.1. Prezentare general
n cadrul acestei lucrri de licen mi propun, pentru a pune n practic
noiunile teoretice explicitate, crearea unei aplicaii de tip client-server i anume a
unui client i al unui server de chat text i audio.
Proiectul a fost realizat n Netbeans 7.1.2, utiliznd pentru interfaa grafic
pluginul Swing. Folosind Swing, interfaa grafic a aplicaiei va putea rula pe
majoritatea platformelor desktop importante (precum Windows, Linux i Mac) n
acelai timp pstrnd acelai stil vizual independent de cel standard impus de
sistemele de operare.
n procesul de dezvoltare a aplicaiei s-a trecut prin etapele principale de
dezvoltare a unei aplicaii mari i anume proiectare, dezvoltare, testare i
deployment. Ideea din spatele aplicaiei este una ct se poate de simpl: Programul
trebuie s demonstreze capacitile limbajului Java de a crea aplicaii stabile de tip
client-server, iar ca exemplu sugestiv n acest sens am ales a dezvolta un chat room
n care userii pot comunica ntre ei, att prin text ct i prin voce.
n ceea ce privete comunicarea prin text, programul pune la dispoziie un
chat global pentru toi userii conectai la server i unul privat prin care acetia pot
comunica ntre ei cte doi. Facilitile de voce ofer posibilitatea ca doi utilizatori
conectai la serverul de chat s se sune ntre ei i s comunice folosind microfonul i
boxele sistemului.
Deoarece aceast lucrare are ca scop prezentarea facilitilor oferite de
limbajul Java n privina crerii unei aplicaii de tip client-server, n continuare vor fi
explicitate totalitatea claselor din aplicaia de chat, totodat furniznd detalii
importante de implementare acolo unde este necesar.

22

Aplicaie practic server i client de chat text i audio

3.2. Descrierea pachetelor de clase din sursa serverului


ntruct limbajul Java a fost cel ales pentru crearea aplicaei, acesta fiind unul
orientat pe obiect autentic, fiecare component major a aplicaiei se identific cu o
clas sau un pachet de clase care au funcionalitate nrudit. Este necesar s precizez
faptul c att clientul, ct i serverul sunt proiecte Netbeans separate, deci avem de
a face n fapt cu doua aplicaii i nu cu una singur. Fiecare dintre aceste dou
aplicaii au propriile lor pachete i clase, implementnd funcionalitaile distincte ale
acestora i anume de client, respectiv de server.
Pentru c serverul este nucleul ntregii funcionaliti a aplicaiei create, voi
ncepe prin a detalia strategiile i metodele aplicate n dezvoltarea sa, ncepd de la o
privire de ansamblu i continund cu facilitile oferite de fiecare clas component
n parte.

3.2.1. Privire de ansamblu


Ideea din spatele serverului de chat se identific cu aceea din spatele
majoritii serverelor, fie ele de mail, fiiere sau web, i anume posibilitatea oferirii
facilitilor pentru o multitudine de clieni n mod simultan. Aadar, fiecare client se
va conecta la server pentru a putea ncepe comunicarea cu un altul, fie aceasta n
cadrul chatroom-ului global, n cadrul unui mesaj privat sau al unui apel audio.
Pentru a permite acest lucru, serverul trebuie s poat face o multitudine de task-uri
n mod simultan i anume pe de-o parte s asculte n mod continuu pe socketul de
tip server (precum am detaliat ntr-o seciune anterioara), iar pe de alt parte s
ofere servicii de chat pentru fiecare client n parte. Aici intervine necesitatea utilizrii
firelor de execuie (threaduri). Un server este creat pentru a oferi non-stop servicii
clienilor i a nu ntmpina erori care ar determina stingerea timpurie a acestuia,
indiferent de activitatea clienilor. De aceea unul din elementele principale care au
fost luate n calcul n crearea aplicaiei a fost tratarea excepiilor ce pot aprea n
cadrul deconectrilor instante i neanunate, a ntrzierilor pachetelor de date dintro comunicare dintre server i clieni cu o conexiune mai slab la reea, precum i a
nepotrivirii echipamentelor audio folosite n comunicarea prin voce.
Pornind de la considerentele enunate mai sus, precizez c sursa aplicaiei
server este structurat pe trei pachete Java i anume ApplicationServer,
ApplicationServer.Frames i ApplicationServer.Voice. Chiar dac numele este sugestiv
23

Aplicaie practic server i client de chat text i audio


pentru fiecare dintre acestea, precizez c primul dintre pachete se ocup cu
funcionalitile de baz ale serverului i anume oferirea de servicii de chat prin text
pentru totalitatea clienilor conectai; al doilea conine succinte elemente pentru o
interfa grafic de pornire i oprire a serverului, iar cel de-al treilea conine o clas
ce implementeaz transmiterea de date audio n cadrul voice chat-ului. n continuare
voi prezenta clasele din aceste pachete, oferind o imagine detaliat a program flowului aplicaiei prin prisma metodelor coninute.

3.2.2. Pachetul ApplicationServer


Clasa Main
ApplicationServer conine n primul i n primul rnd clasa Main care constituie
punctul de intrare n aplicaie. Aceasta conine desigur metoda

public static void main(String[] args)

fiind clasicul punct de acces in cadrul unei aplicaii Java. Metoda instaniaz un nou
formular de tipul clasei ControlPanel din pachetul ApplicationServer.Frames. Prin
intermediul formularului instaniat se va putea apsa un buton de start pentru
pornirea efectiv a serverului.
Aplicaia compilat i gata de distribuie (care este sub forma unui pachet
executabil .jar format din fiiere .class corespunztoare claselor a cror surs sunt
.java-urile din pachetele explicitate) va avea, deci, ca punct de start clasa Main. Sub o
platform precum Windows deschiderea prin dublu click a fiierului .jar este acelai
lucru cu rularea din shell a comenzii:

java -jar ApplicationServer.jar

unde, dup cum observm ApplicationServer este numele executabilului Java


corespunztor aplicaiei server.

Clasa Connection
Aceast clas definete o conexiune ntre server i un client. Fiecare client
conectat la server se va identifica printr-un obiect de tip Connection.
n continuare voi numi cmpurile din clasa Connection care definesc obiectul
conexiune:
24

Aplicaie practic server i client de chat text i audio

Socket clientSocket

reprezinta socketul clientului a crei conexiune e reprezentata de obiectul


conexiune curent. Acest socket va fi creat n momentul conectrii cu succes a
unui client la server.

VoiceConnection voiceConnection

este un obiect de tip VoiceConnection care conine informaii (cmpuri) i


metode despre o eventual conexiune de voce ntre clientul corespunztor
obiectului Connection curent i un alt client. Mai multe detalii despre clasa
VoiceConnection vor fi date n cadrul seciunii dedicate pachetului
ApplicationServer.Voice din care aceasta face parte.

String name

este un string folosit pentru stocarea numelui de utilizator al clientului


corespunztor obiectului conexiune curent.

ObjectOutputStream oos

este fluxul de ieire asociat socket-ului client n momentul conectrii la server.


Prin acest flux se vor putea transmite date ctre client.

ObjectInputStream ois

este fluxul de intrare asociat socket-ului client n momentul conectrii la


server. Prin acest flux se vor putea primi date de la client.

Avnd acum cunotine depline despre cmpurile clasei ce definesc obiectul


conexiune, este uor n continuare s explicm metodele clasei, fcndu-ne o idee de
ansamblu asupra operaiilor i funcionalitilor implementate n aceasta:

static public void sendUserListUpdate()

este o metod care scrie n fluxul de ieire al tuturor conexiunilor clienilor de


pe server un string ce conine o directiv intern pentru actualizarea listei de
clieni online, adugnd utilizatorul nou conectat (corespunztor obiectului
conexiune curent). Aceast directiv va fi interpretat de fiecare aplicaie
client care o primete, adugnd n lista local de utilizatori online i pe
utilizatorul nou conectat.

public void changeNick(String line)

25

Aplicaie practic server i client de chat text i audio


este o metod care schimb numele utilizatorului corespunztor conexiunii
curente ntr-un altul specificat n parametrul line, apoi trimite o directiv de
update sub forma unui string tuturor celorlali utilizatori conectai la server
prin care cere actualizarea de nume i pe partea de client. Asemeni directivei
de update din cazul apelului metodei sendUserListUpdate aceasta va fi
procesat de ctre client pentru a actualiza noul nume al clientului vizat din
lista sa local de utilizatori online.

public void sendPrivateMessage(String line)

trimite un mesaj privat unui utilizator conectat la server.


Metoda primete un parametru care conine o directiv intern sub form de
string de forma:

:$destinatar$mesaj

n continuare, funcia tokenizeaz directiva primit extrgnd destinatarul i


mesajul care trebuie trimis ctre el iar apoi efectueaz o scriere n fluxul de
ieire oos care va transmite efectiv mesajul clientului specific destinatarului
tot sub forma unei directive, care are forma:

:$expeditor$mesaj

Aceasta directiv va fi tokenizat la rndul ei pe client extrgnd expeditorul i


mesajul iar rezultatul va fi afiarea unui mesaj privat cu specificaia c provine
de la un anumit expeditor.

public void sendSystemMessage(String message)

trimite un mesaj sistem utilizatorului corespunztor obiectului conexiune


curent. Acest mesaj este de obicei o eroare server-side sau un anun.

public void sendWorld(String line)

trimite un mesaj specificat n parametru de forma

nume$mesaj

tuturor clientilor conectati la server. Acest mesaj va fi afiat de toate aplicaiile


client conectate la server i reprezint de fapt un mesaj din chat-ul global.

static public void sysSendWorld(String line)

26

Aplicaie practic server i client de chat text i audio


trimite un mesaj sistem tuturor clienilor conectai la server. De obicei, acest
mesaj este un anunt de conectare la server, prsire a serverului sau
schimbare de nume a unuia dintre utilizatori.
Mesajul va fi interpretat la primire de fiecare aplicaie client i va l va afia n
cadrul ferestrei de chat global.

public void sendError(String error)

este o funcie pentru trimiterea unui mesaj de eroare pentru a fi afiat


clientului corespunztor obiectului conexiune curent.

receiveDisconnect()

este o metod ce se va apela n cazul unei deconectri anunate a unui client


de la server. n cadrul acesteia se nchide socket-ul conexiunii curente, se
elimin clientul curent din lista de utilizatori conectai la server i se trimite
prin intermediul metodei sendUserListUpdate() o actualizare a listei de clieni
online tuturor celorlali utilizatori conectai.

Connection(Socket socket)

este constructorul pentru clasa Connection, care ia ca parametru un socket de


tip client. Acest constructor va fi apelat n momentul crerii obiectului
conexiune, ca urmare a conectrii unui nou client la server. n cadrul
constructorului se atribuie socketul din parametru referinei socket din
obiectul nou creat i se stabilesc fluxurile de intrare i de ieire ce vor fi
folosite pentru transmiterea i primirea datelor prin socket. Imediat dup
aceasta, se primete de la client numele acestuia de utilizator i acesta se
atribuie cmpului name al obiectului conexiune pentru a putea identifica pe
viitor conexiunea prin numele de utilizator. Lista de clieni conectai la server
este actualizat apoi, adugnd i noul client conectat.

public void run()

este metoda care o suprascrie pe cea din interfaa Runnable implementata de


obiectul conexiune. Prin implemetarea acestei metode orice obiect conexiune
va putea rula logica metodei run() intr-un thread nou pe server asigurnd
execuia paralel a operaiilor cerute de fiecare client n parte. Astfel, serverul
de chat ndeplinete unul din rolurile principale ale sale i anume asigurarea
conexiunilor simultane din partea unei multitudini de clieni.

27

Aplicaie practic server i client de chat text i audio


n logica metodei se gsete un ciclu while care va rula pn la deconectarea
clientului de la server. Aici se fac citiri din fluxul de intrare asociat socket-ului
conexiunii curente i n funcie de irul de caractere primit se va lua o aciune.
irul de caractere primit poate fi fie un simplu mesaj text destinat tuturor
clienilor de pe server, caz n care se va apela sendWorld(mesaj) sau o
directiv care cere aciuni speciale.
Directivele care pot aprea n cadrul String-ului primit sunt:
:$destinatar$mesaj
pentru transmiterea unui mesaj privat de la clientul corespunztor conexiunii
curente ctre un anumit destinatar specificat n cadrul directivei (se va apela
metoda sendPrivateMessage(...) explicat anterior);
:quit
pentru deconectarea anunat a clientului corespunztor conexiunii curente
de la server (se va apela metoda receiveDisconnect() explicat anterior);
:nick$nume_nou
pentru schimbarea numelui de utilizator pentru clientul curent n numele nou
specificat n directiv (se va apela metoda changeNick() explicat anterior);
:voice$destinatar
pentru iniierea unui apel voce ntre clientul corespunztor obiectului
conexiune curent i un altul specificat n destinatar prin nume. Aici se va
iniializa cmpul voiceConnection al obiectului conexiune cu o conexiune nou
de voice (obiect de tipul clasei VoiceConnection din ApplicationServer.Voice) i
se va apela metoda makeCall() a acestui obiect ce va iniia un apel ctre
destinatarul specificat n directiv.
Tratarea erorilor de citire din fluxul asociat socketului conexiunii curente joac
n cadrul metodei run() un rol deosebit de important. Blocul try...catch n care
este nchis tokenizarea directivelor va prinde erorile ce pot interveni n cazul
unei deconectri neanunate i va apela funcia receiveDisconnect() pentru
terminarea conexiunii ntr-o astfel de situaie.

28

Aplicaie practic server i client de chat text i audio


Clasa Server
Aceast clas implementeaz mecanismul prin care serverul ateapt
ntotdeauna un nou client s se conecteze i aciunile luate n momentul conectrii.
n continuare voi detalia cmpurile din clasa Server folosite n cadrul acceptrii
de noi clieni.

private static int maxConn

reprezint numrul maxim de conexiuni pe care le va permite serverul la un


moment dat. Acest numar este fixat n cadrul interfeei grafice afiat la
pornirea aplicaiei server i anume formularul de tipul ControlPanel din
pachetul ApplicationServer.Frames.

private static Map<String, Connection> matchCon

este un tabel asociativ ntre o mulime de nume de clieni (String-uri) i o


mulime de obiecte de tipul Connection care, dup cum am vzut anterior
conin totalitatea mijloacelor de comunicare prin socket-uri ntre server i
respectivii clieni.
n acest cmp se vor stoca totalitatea conexiunilor clienilor care iau legtura
cu serverul. Datorit faptului c se in minte i numele de utilizator ale
clienilor se va putea accesa n mod simplu obiectul conexiune al unui client
prin apelarea metodei
matchCon.get(nume_client)

Dup cum tim avnd acces la obiectul conexiune al unui client putem aplica
orice operaie suportat de transmitere de date nte acesta i restul clienilor
prin intermediul metodelor din clasa Connection.

private static int con_count

este un cmp care ine minte numrul de conexiuni curente la server. Acesta
va fi, evident incrementat n momentul n care un nou client este acceptat de
ctre server.

La acest punct, odat cu cunoaterea cmpurilor clasei Server se poate detalia


asupra funcionalitilor implementate de metodele sale.

29

Aplicaie practic server i client de chat text i audio


ntruct cmpurile prezentate mai sus au fost fcute private pentru o mai
bun securitate a integritii datelor, din necesitatea accesrii directe a cmpurilor
respective s-au creat getteri pentru fiecare dintre ele. Amintim:

public static int getConnectionsCount()

care returneaz numrul de conexiuni stocat n cmpul con_count;

public static Connection getConnection(String s)

care returneaz direct obiectul Connection pentru clientul a crui nume e dat
ca parametru din tabelul asociativ matchCon unde sunt stocate toate
conexiunile;

public static Map<String, Connection> getConnectionsMap()

care returneaz ntregul tabel asociativ al conexiunilor.

Trecem mai departe la nucleul clasei Server de acceptare a noilor clieni i


anume metoda run() care o suprascrie pe cea din interfaa Runnable implementat
de clas. Reamintesc c un obiect al crui tip este o clas care implementeaz
Runnable poate fi dat ca parametru unui constructor al unui Thread, iar apoi prin
apelarea metodei start a thread-ului se va executa ntr-un fir de execuie paralel
codul din metoda run(). n cazul nostru acest mecanism este folositor n ceea ce
privete separarea logicii serverului de minimalista interfa de pornire i oprire a
acestuia care va folosi un thread separat. n acest mod interfaa nu va trebui s
atepte dup procesele serverului pentru a putea fi folosit. Rularea n acelai thread
a interfeei i a logicii serverului ar fi de fapt imposibil, deoarece odat cu pornirea
proceselor serverului (care conin o bucl infinit) interfaa s-ar bloca ntr-o continu
ateptare. Astfel serverul nu ar mai putea fi oprit din interfa.
ntreg mecanismul de acceptare a noilor clieni este explicat n continuare prin
detalierea metodei run().

public void run()

Primul lucru care se ntmpl n cadrul metodei run() este iniializarea


referinei tabelului asociativ matchCon cu cea a unui nou tabel creat cu
operatorul new de dimensiunea numrului maxim de conexiuni permise ce
este stocat n cmpul maxConn. Codul folosit este:
matchCon = new HashMap<String, Connection>(maxConn);

30

Aplicaie practic server i client de chat text i audio


Se creeaz apoi un socket de tipul ServerSocket care va fi folosit pentru
acceptarea de noi clieni prin urmtoarea linie de cod:

ServerSocket listener = new ServerSocket(27018);

Parametrul este numrul portului care va fi folosit pentru transmiterea datelor


text ntre server i clieni. Prin date text nelegem mesaje i directive. Precizez
acest lucru deoarece atunci cnd vom vorbi despre apeluri audio, se va folosi
un alt socket server i un alt port.
Urmeaz apoi ciclul while (infinit) pentru acceptarea de noi clieni. n cadrul
acestuia, se apeleaz metoda blocant

listener.accept()

a obiectului ServerSocket tocmai creat. Apelul acestei metode ntoarce un


obiect de tip Socket (socket de tip client). Acest obiect va fi dat ca parametru
constructorului unui obiect de tip Connection crend astfel o conexiune la
server pentru un nou client.
n urma pasului intern al constructorului obiectului conexiune se face face un
read din fluxul de date transmis de client care va afla numele de utilizator al
clientului. Totodat se va rula logica intern a unei conexiuni ntr-un nou
thread care primete obiectul conexiune ca parametru i execut metoda
run() a acestuia.
Avnd acum att numele ct i obiectul de tip conexiune pentru noul client se
va crea o nou nregistrare corespunztoare acestor date n lista de useri
coninut n tabelul asociativ matchCon. n acest moment serverul are toate
datele necesare pentru a oferi servicii de chat text clientului nou conectat.
Mai rmne dect s ntiinm toi utilizatorii conectai la server de existena
unui nou client. Acest lucru se face n doi pai. n primul rnd se invoc
metoda static Connection.sendUserListUpdate() pentru a actualiza listele
locale de pe fiecare client astfel nct s conin i noul user. Al doilea pas
presupune transmiterea unui mesaj sistem ctre toi userii conectai care s
specifice conectarea noului client la server. Acesta va fi afiat n cadrul chatului global pe fiecare client, inclusiv pe cel nou conectat i va fi de forma:

*** User <name> connected ***

Nu n ultimul rnd, se va incrementa numrul conexiunilor existente (variabila


con_count) cu 1.
31

Aplicaie practic server i client de chat text i audio


De precizat este faptul c acest mecanism de acceptare nu va permite
conectarea unor clieni noi dect dac numrul conexiunilor existente este
mai mic dect numrul maxim de conexiuni permise (condiionnd acest lucru
printr-o instruciune if). n momentul n care un client este deconectat
variabila con_count va fi decrementat cu o unitate.
Pn la acest punct, au fost prezentate totalitatea detaliilor de implementare
pentru facilitile de chat text. n succesiunea logic a ideilor, urmeaz prezentarea
pachetului ApplicationServer.Voice care conine clasa VoiceConnection ce se ocup
cu manipularea datelor audio n cadrul unui apel voce ntre doi clieni ai serverului.

3.2.3. Pachetul ApplicationServer.Voice

Clasa VoiceConnection
Ca i n cazul claselor prezentate anterior, voi ncepe prin expunerea
cmpurilor din clas:

static ServerSocket serverVoiceSocket

este socketul de tip server care va asculta pentru conexiuni destinate


apelurilor audio ntre doi useri. Acesta este un cmp static ceea ce presupune
c va exista o singur instan a acestuia indiferent de cte obiecte
VoiceConnection sunt create.

private Socket clientVoiceSocket

este socketul de tip client care va fi creat odat cu stabilirea unei conexiuni
audio ntre server i clientului corespunztor obiectului conexiune audio
curent.

private Thread transmission

este un fir de execuie (thread) care va executa operaiile de transmitere a


datelor audio de la un expeditor la un destinatar.

private String callerName

este numele utilizatorului care iniiaz apelul.

private String calleeName

32

Aplicaie practic server i client de chat text i audio


este numele utilizatorului care este apelat.

private BufferedInputStream input

este un flux de date folosit n primirea de informaii de la clientul a crei


conexiune de voce asociat este obiectul conexiune de voce curent (cel care
suna).

private BufferedOutputStream out

este un flux de date folosit n transmiterea de informaii ctre clientul ai crei


conexiune de voce asociat este obiectul conexiune de voce curent (cel care
suna).

private byte tempBuffer[] = new byte[10000]

este un buffer folosit n transmiterea informaiei audio prin fluxurile de intrare


i de ieire asociate obiectului conexiune de voce curent. Este nevoie s
folosim un buffer ntruct informaia este potenial infinit (atta timp ct un
emitor are microfonul deschis se transmit n mod continuu date iar acestea
trebuie trimise pe seciuni receptorului)
Continui prin prezentarea logicii (a metodelor) unei conexiuni de voce, adic a
ansamblului de pai pe care i urmeaz serverul pentru a transmite informaia audio
de la un client la altul.
n primul rnd trebuie precizat faptul c VoiceConnection are un bloc static de
iniialiare (numit i constructor static) care creeaz socket-ul server necesar
acceptrii apelurilor audio de la clienii conectai la server. Un bloc static de
iniializare este executat n momentul crerii unui obiect din clasa respectiv sau n
momentul apelrii unei metode statice din aceasta.
n cazul clasei VoiceConnection, ideea din spatele folosirii constructorului
static este faptul c atta timp ct nu se fac conexiuni audio ntre clienii conectai la
server (nzestrai momentan doar cu faciliti de comunicare text) nu este nevoie de
ascultarea continu pentru conexiuni audio. Mai simplu spus, atta timp ct nici unui
dintre clienii care s-au conectat la server i comunic prin mesaje globale sau private
nu iniiaz un apel audio, facilitile de voce sunt complet dezactivate. Abia n
momentul n care unul dintre clieni iniiaz un apel audio se iniializeaz facilitile
de voce ale serverului. Motivul alegerii acestei abordri se poate justifica prin faptul
c aplicaia de chat a fost conceput iniial pentru stricta comunicare prin text,
ulterior adugnd i opiunea de comunicare audio. Pornind de la acest considerent
33

Aplicaie practic server i client de chat text i audio


nu crem un socket pentru apelurile audio pn cnd nu este nevoie s folosim
funcionalitile de voce ale aplicaiei.
n afara blocului static de iniializare, clasa are i un constructor:

public VoiceConnection(String caller, String callee)

care atribuie cmpurilor callerName i calleeName valorile cu acelai nume din


parametri.
nainte de a prezenta metoda de iniiere a unui apel este necesar a explica
funcionalitatea a dou alte metode folosite:

public void bindSocket()

apeleaz metoda accept() a socket-ului server pentru conexiuni de voce n


scopul conectrii unui client nou la serviciul de voice chat. Metoda accept()
ntoarce un obiect de tip socket care este atribuit cmpului clientVoiceSocket
al obiectului curent.
Apoi, cmpurile input i output ale clasei sunt iniializate cu streamurile de
intrare i ieire de la socket-ul client tocmai creat.

public void transmitTo(final BufferedOutputStream b)

este principala metod de transmisie a datelor audio ntre doi clieni conectai
la server. Obiectul curent este considerat cel care trasmite, iar fluxul primit ca
parametru este cel al obiectului spre care se dorete transmiterea datelor
audio.
n cadrul metodei, se creeaz un nou thread, n care printr-un ciclu while se
transmite, buffer cu buffer, informaia primit de la clientul asociat obiectului
conexiune curent, ctre clientul al crui flux e primit ca parametru. Notm
faptul c, referina thread-ului creat este atribuit cmpului transmission al
obiectului curent.
Aceast metod este nucleul ntregii comunicri de date audio ntre clienii
conectai la server. Se observ faptul c inafara necesitii folosirii unui buffer
pentru transmiterea gradual a datelor, modul de transmitere este unul
obinuit ca i n cazul irurilor de caractere.

Pentru iniierea unui apel audio se folosete urmtoarea metod:

public void makeCall()

34

Aplicaie practic server i client de chat text i audio


Primul pas n stabilirea legturii de comunicare prin voce ntre clientul al crui
obiect VoiceConnection este cel curent i un alt client conectat la server, este
crearea unui obiect de tip VoiceConnection i pentru cellalt client.
Pentru acest lucru se vor executa urmtoarele linii de cod:

VoiceConnection callee =
(Server.getConnection(calleeName).voiceConnection = new
VoiceConnection(calleeName, callerName));

Am obinut, astfel, referina la obiectul conexiune al clientului apelat.


n continuare apelm metoda bindSocket() explicat mai sus pentru ambele
conexiuni de voce (cea a iniiatorului apelului reprezentat de obiectul curent
i cea a utilizatorului apelat reprezentat de conexiunea tocmai creat la pasul
anterior).
Urmtorul pas este apelul metodei transmitTo() att pe obiectul curent cu
parametrul fluxului de ieire al conexiunii clientului sunat, ct i pe obiectul
clientului sunat cu parametrul fluxului de ieire out al obiectului curent. Astfel
se creeaz dou threaduri, unul pentru transmiterea de informaie audio de la
iniiatorul apelului la clientul apelat i unul, invers, de la clientul apelat la
iniiatorul apelului.
Codul folosit pentru crearea acestei transmisii bidirecionale de informaie
audio este urmtorul:

transmitTo(Server.getConnection(calleeName).voiceConnection.ou
t);
callee.transmitTo(this.out);

Rezumnd, legtura audio dintre doi clieni conectai la server s-a realizat prin
construcia a dou obiecte VoiceConnection cu interdepentene puternice, care i
transmit, prin thread-uri separate, n mod continuu date i le trimit ctre
dispozitivele audio de redare ale sistemelor vizate.

35

Aplicaie practic server i client de chat text i audio

3.2.4. Pachetul ApplicationServer.Frames

Clasa ControlPanel
Aceast clas implementeaz minimalista interfa grafic cu butoanele de
pornire i oprire a serverului. Totodat n cadrul interfeei afiate prin instanierea
formularului Swing definit n clas se poate seta numrul maxim de conexiuni pe care
le poate permite serverul la un moment dat.
ntruct propun detalierea controalelor Swing n special pentru aplicaia client,
voi omite o descriere amnunit a logicii din spatele acestei interfee grafice.

3.3. Descrierea pachetelor de clase din sursa clientului


3.3.1. Prezentare general

Odat terminat explicarea claselor i a modului de funcionare pentru


aplicaia server propun, n succesiunea logic a ideilor s discut despre aplicaia
client.
Asemeni serverului, clasele sursei clientului sunt organizate n pachete.
Acestea sunt: ApplicationClient, ApplicationClient.Frames i ApplicationClient.Voice.
Primul dintre ele conine clase ce servesc la trimiterea i primirea de mesaje text i
voce, al doilea conine elementele interfeei grafice, iar clasele celui de-al treilea sunt
folosite pentru redarea i preluarea de date audio prin dispozitivele sistemului.

3.3.2. Pachetul ApplicationClient

Voi ncepe prin prezentarea pachetului ApplicationClient care implementeaz


ntreg sistemul de chat prin text i voce. Prezentnd anterior mecanismele de
transmitere a mesajelor din perspectiva serverului, detalierea acestora pentru client
vor intregi imaginea de ansamblu asupra modului de funcionare a ntregului model
client-server.
36

Aplicaie practic server i client de chat text i audio


Punctul de intrare n aplicaie este clasa principal Main care conine clasica
medod:

public static void main(String args[])

n cadrul acesteia se va crea o instan a ferestrei principale de chat definit n clasa


ClientFrame din pachetul ApplicationClient.Frames. Totodat se va instania un
formular pentru furnizarea detaliilor de conectare la server specificat n clasa
NameChooser din pachetul ApplicationClient.Frames. Aceste clase grafice vor fi
detaliate mai trziu n seciunea despre pachetul din care fac parte.

Clasa Connection
Asemeni clasei Connection de pe server, aceast clas va implementa
totalitatea metodelor de transmitere a mesajelor prin socket-uri, va gestiona
fluxurile de intrare i de ieire asociate socket-urilor i va oferi mijloacele necesare
realizrii unei conexiuni audio cu un alt client.
Este important s precizez faptul c interfaa Runnable este implementat de
clasa Connection, fapt ce o nzestreaz cu posibilitatea rulrii logicii necesare pentru
interpretarea mesajelor primite de la server ntr-un thread separat.
Cmpurile clasei Connection sunt:

Socket socket

este socket-ul care va fi folosit pentu conectarea i comunicarea cu serverul a


mesajelor text i a directivelor ce necesit tratament special.

Socket voiceSocket

este socket-ul care va fi folosit pentru transmiterea i primirea informaiei


audio n cadrul unui apel voce.

ObjectInputStream ois

este un flux de intrare care va fi iniializat cu cel asociat socket-ului socket


dup conectarea la server.

ObjectOutputStream oos

este un flux de ieire care va fi iniializat cu cel asociat socket-ului socket dup
conectarea la server.
37

Aplicaie practic server i client de chat text i audio


Dup expunerea cmpurilor clasei, se poate face prezentarea logicii de aplicaie
implementat n cadrul metodelor.

public void connect(String address)

este metoda care face legtura cu serverul, iniializnd cmpul socket al


obiectului conexiune cu un nou obiect de tipul Socket. Constructorul acestui
obiect ia doi parametri: primul dintre ei este adresa serverului (preluat din
parametrul metodei) iar al doilea este un port (prin convenie s-a stabilit c
portul folosit att de server ct i de client pentru transmiterea datelor este
27018). Dup conectarea la server cmpurile oos i ois ale obiectului
conexiune vor fi iniializate cu fluxurile de ieire, respectiv de intrare ataate
socket-ului care tocmai s-a conectat la server.
Dup aceasta, n fluxul de ieire oos se va scrie numele clientului pentru ca
serverul, i ca o consecin ceilali clieni, s indenfice pe viitor clientul curent
printr-un ir de caractere al numelui.

public void worldSend(String text)

trimite ctre server mesajul text din parametru cu scopul de a fi difuzat


tuturor clienilor conectai la server.
Trimiterea se face printr-o scriere n fluxul de ieire al socket-ului socket
apelnd:
oos.writeObject(text);

public void worldReceive(String text)

apeleaz metoda showGlobalMessage(text) a obiectului formular de chat


(clasa ClientFrame) cu scopul afirii unui mesaj text n cadrul ferestrei chatului global.

public void userListReceive(String text)

interpreteaz o directiv de actualizare a listei de utilizatori conectai la server


i adaug n lista local a aplicaiei client de useri conectai la server i pe
userul nou conectat la server specificat n directiv.

public void userReceive(String text)

primete ca parametru o directiv specific unui mesaj privat de forma:


:$expeditor$mesaj

38

Aplicaie practic server i client de chat text i audio


Metoda tokenizeaz directiva primit extrgnd destinatarul i mesajul n
variabile separate, apoi, printr-un apel al metodei
showPrivateMessage(expeditor, mesaj) corespunztoare instanei
formularului principal al aplicaiei de chat (de clasa ClientFrame) va afia o
fereastr coninnd mesajul privat respectiv.

public void userSend(String dest, String message)

trimire textul din parametrul message ca mesaj privat utilizatorului cu numele


din parametrul dest. Trimiterea este condiionat de existena unui utilizator
cu numele specificat ca destinatar.
Codul folosit pentru trimiterea mesajului este:

oos.writeObject(":$" + dest + "$" + message);

Se observ c, n fluxul de ieire al socket-ului conexiunii la server a clientului


curent, nu se face scrierea unui simplu mesaj, ci a unei directive care va fi
interpretat de server (vezi prezentarea metodei run() a clasei Connection din
pachetul ApplicationServer).

public Boolean isAlive()

este o metod ce returneaz true dac socket-ul pentru mesaje text este nca
n conexiune cu serverul, sau false n caz contrar. Pentru aflarea acestei
informai se folosete rezultatul boolean returnat de apelarea metodei
socket.isBound().

public void voiceReceive(String text)

primete ca parametru String o directiv de forma:


:%nume_apelant

Aceast metod va fi apelat n momentul n care un client conectat la server


va cere a efectua un apel audio ctre clientul reprezentat de obiectul Connection
curent. Din directiva primit, numele apelantului va fi extras i aplicaia client va fi
ntiinat c un utilizator cu acel nume dorete stabilirea unei conexiuni audio.
ntiinarea se va face prin instanierea unui formular (de tipul clasei Answerer
din pachetul ApplicationClient.Frames) ce va permite acceptarea sau ignorarea
apelului cerut de cellalt client.

39

Aplicaie practic server i client de chat text i audio


n cazul acceptrii apelului se va creea un nou socket n scopul transmiterii
bidirecionale a informaiei audio ntre cei doi participani la conversaie. Referina
acestui nou socket va fi atribuit cmpului voiceSocket al obiectului conexiune
curent.
Dup crearea socket-ului, metoda voiceReceive pred tafeta metodei
captureAudio(voiceSocket) a clasei Receiver din pachetul ApplicationClient.Voice care
se va ocupa cu manipularea fluxurilor de date audio dintre clientul apelat i cel care a
iniiat apelul. Bineneles, toate transmiterile de date se fac prin intermediul
serverului i nu client ctre client.
Voi detalia n continuare metoda run() care intercepteaz mesajele i
directivele primite de la server i ia aciunile corespunztoare.
Trebuie specificat faptul c metoda run() va rula ntr-un thread separat astfel nct
logica aplicaiei client ce ine de comunicarea de date prin socket-uri este separat
de logica afirii interfeei grafice.
public void run()
Metoda conine un ciclu while (infinit) care primete date text din fluxul de
date de intrare asociat socket-ului socket. irurile de caractere primite sunt fie
mesaje text destinate chat-ului global, fie directive care necesit tratare
special. n primul dintre cazuri, irul respectiv de caractere e dat ca
parametru metodei worldReceive care va conduce la afiarea lui n formularul
de chat global.
Directivele ce pot fi primite de la server sunt:

:$expeditor$mesaj

atunci cnd este vorba despre primirea unui mesaj privat, caz n care se
apeleaz metoda userReceive() explicat anterior;

:%apelant

pentru ntiinarea aplicaiei de un apel voce cerut de un alt client, caz n care
se va apela metoda voiceReceive() explicat anterior;

:<client_nou sau :>client_nou


pentru ntiinarea aplicaiei client despre conectarea, respectiv deconectarea
unui alt client de la server.

40

Aplicaie practic server i client de chat text i audio

Clasa Client
Clasa Client ofer versiuni de o abstractizare mai mare ale metodelor de realizare a
unei conexiuni, de trimitere a unui mesaj global i de trimiterea a unui mesaj privat.
Aceasta are dou cmpuri:

Connection connection

reprezint singura conexiune cu serverul a aplicaiei client.

Thread receiveThread

este o referin de tip Thread careia i se va atribui firul de execuie n care va


rula metoda run() a conexiunii connection dup legarea cu succes la server.
Metodele clasei Client sunt:

public void connectToServer(String address)

care creeaz o conexiune la serverul specificat la adresa din parametru. Dup


realizarea cu succes a conexiunii prin apelarea metodei connect(address) a
obiectului conexiune creat se trece la crearea thread-ului care va rula logica
metodei run() a conexiunii. Referina acestui thread va fi atribuit cmpului
receiveThread al clasei.

public void sendGlobalMessage(String text)

care nu face dect s apeleze metoda worldSend(text) a obiectului conexiune


refereniat de cmpul connection i s implementeze obligatoria prindere a
excepiilor pentru aceast operaie.

public void sendPrivateMessage(String dest, String message)

care nu face dect s apeleze metoda userSend(dest,message) a obiectului


conexiune refereniat de cmpul connection i s implementeze obligatoria
prindere a excepiilor pentru aceast operaie.

41

Aplicaie practic server i client de chat text i audio

3.3.3. Pachetul ApplicationClient.Voice

Acest pachet conine, dup cum a fost descris i n prezentarea general a


aplicaiei client, totalitatea mecanismelor de comunicare i redare a datelor audio
din cadrul apelurilor vocale.
Pachetul conine trei clase, fiecare cu o funcionalitate distinct i
independent: DeviceGetter, Receiver i SoundPlayer.

Clasa DeviceGetter
Aceast clas se ocup cu setarea unui dispozitiv audio de intrare (input), de
obicei un microfon, care va fi folosit ca surs a datelor audio ale clientului n cadrul
unui apel vocal.
Avem doar un singur cmp:

static int selectedDevice

care va memora index-ul dispozitivului folosit ca input n apelurile vocale


dintr-o list a dispozitivelor audio ale sistemului care pot fi folosite ca surs.
Clasa dispune de dou metode:

public static void setInputDevice(int index)

care seteaz cmpul selectedDevice la o alt valoare specificat n parametrul


de intrare. Prin apelarea acestei metode se alege dispozitivul folosit ca surs n
transmiterea de informaii audio ntre clientul curent i cellalt participant la
conversaie.

public static DefaultComboBoxModel updateDevices()

este o metod care ntoarce o list cu denumirile dispozitivelor audio ale


sistemului care pot fi folosite ca surs ntr-un apel vocal.
n cadrul acesteia se creeaz vectorul
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();

i este populat cu totalitatea specificaiilor dispozitivelor audio cu capaciti


de nregistrare ale sistemului.
42

Aplicaie practic server i client de chat text i audio


De la acest vector, printr-un ciclu for se construiete un alt vector, de Stringuri, care s memoreze doar numele fiecruia dintre dispozitive.
ntr-un final, metoda ntoarce o list de tipul DefaultComboBoxModel creat
cu elementele vectorului de denumiri, care va putea fi folosit ca baz de
elemente pentru un drop-down box din interfaa grafic. Acel drop-down box
va fi folosit pentru selectarea facil a dispozitivului audio surs n momentul
efecturii unui apel.

Clasa Receiver
Clasa Receiver este cea care se ocup de nteaga transmitere, procesare i
redare a informaiei audio n cadrul unui apel vocal.
ntruct un singur apel vocal poate exista la un moment dat ntr-o aplicaie
client, am ales design pattern-ul Singleton pentru inplementarea clasei. O clas
singleton presupune existena unei singure instane a acesteia. Pentru acest lucru, se
definete un cmp de tipul clasei respective n interiorul acesteia care va memora
referina la unica instan a clasei. n plus, constructorul clasei devine privat iar o
metod care s furnizeze unica instan a clasei se definete.
n cazul clasei receiver pattern-ul singleton este dat de urmtorul bloc de cod:

private static Receiver instance;


protected Receiver() {
instance = this;
}
public static Receiver getInstance() {
if (instance == null) {
instance = new Receiver();
}
return instance;
}

n continuare voi prezenta cmpurile clasei, pentru ca apoi s explic metodele


folosite n transferul i redarea informaiei audio.

43

Aplicaie practic server i client de chat text i audio

ByteArrayOutputStream byteArrayOutputStream

este un flux de bii care va fi folosit n popularea unui buffer folosit n


transferul pe seciuni a informaiei audio ntre client i server.

AudioFormat audioFormat;

este un cmp n care se va stoca un obiect ce definete formatul audio folosit


de voice chat. Audioformat e o clas din pachetul javax.sound.sampled.

TargetDataLine sendDataLine

va stoca obiectul de tip javax.sound.sampled.TargetDataLine ce definete linia


audio a sistemului corespunztoare dispozitivului audio surs (microfon).

SourceDataLine receiveDataLine;

va stoca obiectul de tip javax.sound.sampled.SourceDataLine ce definete linia


audio a sistemului corespunztoare dispozitivului audio de redare (boxe).

InputStream vis

este un cmp caruia n va fi atribuit referina fluxului de intrare al socket-ului


pentru conexiuni de voce din obiectul conexiune. Prin acest flux se vor primi,
prin intermediul serverului datele audio de la cellalt client implicat n
convorbire.

OutputStream vos

este un cmp caruia i va fi atribuit referina fluxului de ieire al socket-ului


pentru conexiuni de voce din obiectul conexiune. Prin acest flux se vor trimite,
prin intermediul serverului, datele audio ctre cellalt client implicat n
convorbire.

boolean inCall = false

este o variabil boolean care va fi setat true n momentul n care clientul se


va afla ntr-o convorbire. Imediat dup terminarea convorbirii, variabila va fi
setat napoi cu false.
Aceast variabil va fi de folos pentru a restriciona numrul conexiunilor de
voce simultane posibile la una singur.

Trecem la detalierea logicii clasei prin prezentarea metodelor acesteia:


44

Aplicaie practic server i client de chat text i audio

public void captureAudio(Socket voiceSocket)

n aceast metod se seteaz variabila inCall ca fiind true, pentru a marca


faptul c un apel e n curs de desfurare. Se seteaz apoi variabilele vis i vos
cu fluxurile de intrare, respectiv de ieire ale socket-ului voiceSocket.
Variabila audioFormat este iniializat prin apelul unei metode
getAudioFormat a clasei (va fi explicat ulterior).
O variabil dataLineInfo de tipul DataLine.Info este creat printr-un
constructor, care ia ca parametru variabila audioFormat pentru a specifica
formatul audio ce trebuie suportat de un dispozitiv pentru a putea fi folosit n
voice chat.
Se ia apoi o referin mixer de tipul javax.sound.sampled.Mixer a dispozitivului
audio selectat ca sursa n cadrul clasei DeviceGetter.
Variabila liniei audio surs pentru clientul curent, ce va fi folosit pentru
obinerea irului de bii corespunztori informaiei trimise ctre server este
sendDataLine iar aceasta este iniializat prin:
sendDataLine = (TargetDataLine)
sendDataLinemixer.getLine(dataLineInfo);

Linia este apoi deschis i pornit prin apelarea metodelor open i start ale
obiectului sendDataLine.
Se creeaz apoi un fir de execuie nou de tipul CaptureThread, a crui clas
este imbricat n clasa curent (va fi descris ulterior). Acest thread va fi folosit
pentru continua citire a datelor de la dispozitivul surs i trimiterea acestora
ctre server. Threadul este imediat startat.
n mod similar ca i pentru linia audio surs a transmisiei se va proceda i
pentru linia de redare a datelor venite de la server, receiveDataLine. Pentru a
nu repeta raionamentul pe variabile, codul urmtor este relevant:
DataLine.Info dataLineInfo1 = new
DataLine.Info(SourceDataLine.class, audioFormat);
receiveDataLine = (SourceDataLine)
AudioSystem.getLine(dataLineInfo1);
receiveDataLine.open(audioFormat);
receiveDataLine.start();

45

Aplicaie practic server i client de chat text i audio


Asemeni liniei audio surs se creeaz un fir de execuie nou, a crui clas este
imbricat n actuala ( va fi detaliat ulterior). Prin acest thread se va primi
continuu date audio de la server i acestea se vor reda pe boxele sistemului.
Threadul va fi startat imediat.

private AudioFormat getAudioFormat()

este metoda care construiete un obiect AudioFormat care s desemneze un


anumit format audio ales din motive de transmitere rapid dar i cu o calitate
decent a informaiei. Formatul audio ales se observ direct din corpul
metodei:
float sampleRate = 8000.0F;
int sampleSizeInBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleSizeInBits, channels,
signed, bigEndian);

n afara metodelor pe care le-am descris mai sus, dup cum am amintit pe
alocuri, clasa Receiver conine dou clase imbricate care extind Thread i
implementeaz mecanismele de primire i redare, respectiv nregistrare i
trimitere a datelor audio.

class CaptureThread extends Thread

conine metoda run() care va fi rulat de ctre thread-ul obinut prin


instanierea clasei. Aceasta conine un ciclu while ce ruleaz pe tot parcursul
unei convorbiri i nregistreaz datele din dispozitivul surs al sistemului
(microfon) ntr-un buffer, iar apoi le trimite ctre server prin fluxul vos.
Metoda implementeaz un mecanism de tratarea a excepiilor de tipul
try...catch...finally, blocul finally elibernd resursele alocate unei convorbiri
indiferent dac apelul s-a ncheiat cu succes sau cu eroare.

class PlayThread extends Thread

conine metoda run() care va fi rulat de ctre thread-ul obinut prin


instanierea clasei. Aceasta conine un ciclu while ce ruleaz pe tot parcursul
unei convorbiri i primete date audio de la server ntr-un buffer prin fluxul vis,
iar apoi le red pe dispozitivul audio de playback al sistemului (boxe).

46

Aplicaie practic server i client de chat text i audio


Clasa SoundPlayer
Aceast clas implementeaz Runnable, iar metoda

public void run()

a sa este folosit pentru redarea unui sunet de apel n momentul n care se primete
sau se iniiaz un apel .

3.3.4. Pachetul ApplicationClient.Frames. Ghid de utilizare a aplicaiei


client

n acest moment, toat logica de transmitere a datelor ntre server i clieni,


att pentru mesaje text, ct i pentru apeluri vocale, a fost explicat. Mai rmne a
detalia clasele interfeei grafice folosite de ctre client pentru afiarea mesajelor i
facilitarea accesului rapid la funciile de chat.
ntreaga interfa grafic este format din 4 formulare Swing,
corespunztoare a 4 clase: ClientFrame, NameChooser, PrivateChat i Answerer. n
continuare vom prezenta aceste formulare punnd accent pe elementele vizuale.

Clasa (Formularul) NameChooser


Acest formular este primul care este afiat n momentul intrrii n aplicaie. n
cadrul lui se va seta adresa serverului i numele (nick-ul) de utilizator care va
identifica clientul.
Urmtoarea imagine arat aspectul vizual al unei instane a formularului:

47

Aplicaie practic server i client de chat text i audio

Dup cum se observ, formularul are 2 cmpuri, unul etichetat Alias, unde se
va introduce numele de utilizator dorit i unul setat Host unde se va introduce adresa
serverului. Prin apsarea butonului accept dup introducerea cmpurilor se va
ncerca conectarea la server (se apeleaz metodele corespunztoare din clasa Client).
Dup conectarea cu succes la server formularul acesta va disprea lsnd vizibil doar
pe cel specificat de clasa ClientFrame.

Clasa (Formularul) ClientFrame


Aceast formular reprezint de fapt fereastra principal a aplicaiei, fiind dotat
cu totalitatea cmpurilor i butoanelor necesare trimiterii i primirii de mesaje,
precum i efecturii unui apel audio.
Urmtoarea imagine arat aspectul vizual al unei instane a formularului:

48

Aplicaie practic server i client de chat text i audio


Dup cum se observ i din imagine, formularul are o arie text care ocup cea
mai mare parte din acesta, unde se vor afia mesajele din cadrul chat-ului global i
cele sistem (anunuri i erori).
n partea dreapt a formularului se gsete o list (JList) n care sunt afiati toi
utilizatorii conectai la server. Aceast list este actualizat de fiecare dat cnd se
primete o directiv de update de la server (vezi clasa Connection).
Sub aria text pentru mesaje se afl un cmp i un buton pentru trimiterea unui
mesaj text global sau a unei directive ctre server. Eventul pentru apsarea tastei
enter a fost codat pentru a apsa butonul Send pentru o mai uoar trimitere a
mesajelor.
n partea de jos a ferestrei se gsete un drop-down box prin care se poate
seta dispozitivul implicit folosit ca surs audio n cadrul apelurilor voce. De obicei se
va alege microfonul.
Butonul Call va fi folosit pentru apelarea unui utilizator din lista de clieni
conectai la server. Pentru selectarea unui client spre apelare se va face click pe
numele acestuia din lista de utilizatori nainte de a apsa butonul Call. n momentul
n care clientul va fi ntr-un apel, butonul call se va transforma ntr-un buton End a
crei apsare va ntrerupe conexiunea audio curent.
Mai adaug c, executarea unui dublu click pe numele unui utilizator din lista
de clieni va deschide o fereastr de mesaj privat (formularul PrivateChat) prin care
se vor putea trimite mesaje individuale acelui client.

Clasa (Formularul) PrivateChat


Formularul PrivateChat reprezint interfaa grafic pentru comunicarea de
mesaje individuale ntre doi clieni. Spre deosebire de chat-ul global care este parte a
ferestrei principale a aplicaiei (ClientFrame), acest formular nu apare dect fie n
momentul n care fie se primete un mesaj de la un alt client, fie n momentul n care
utilizatorul execut dublu click pe un nume de client din lista de utilizatori conectai
cu scopul trimiterii unui mesaj privat.

49

Aplicaie practic server i client de chat text i audio


Urmtoarea imagine arat aspectul vizual al unei instane a formularului:

Asemeni formularului principal, PrivateChat este dotat cu o arie text pentru


primirea mesajelor i un cmp cu buton pentru trimiterea mesajelor. Trimiterea de
mesaje este simplificat i aici prin redirecionarea evenimentului de apsare a tastei
enter ctre funcia de apsare a butonului Send, deci a trimiterii mesajului.

Clasa (Formularul) Answerer


Formularul Answerer pune la dispoziie o modalitate de a accepta sau respinge
apelurile audio n cadrul aplicaiei client. n momentul primirii unui apel Acest
formular apare iar utilizatorul are la dispoziie 30 de secunde s l accepte. n caz
contrar, dup terminarea timpului, apelul este respins n mod automat. Pe parcursul
afirii formularului un sunet de apel va fi redat prin intermediul mecanismului
implementat n clasa SoundPlayer din pachetul ApplicationClient.Voice.

50

Aplicaie practic server i client de chat text i audio


Urmtoarea imagine arat aspectul vizual al unei instane a formularului:

Dup cum se observ utilizatorul poate face click pe unul dintre cele dou
butoane puse la dispoziie. Apsarea butonului Answer va rspunde la apel iar
butonul etichetat Ignore va bara apelul.

51

4. Concluzii
Pornind de la noiunile teoretice i terminnd cu detalierea unei aplicaii
practice, am reuit s expunem ntreaga metodologie ce trebuie avut n vedere n
crearea aplicaiilor de tip client-server. Limbajul Java, dup cum am demonstrat prin
crearea aplicaiei de chat ofer suficiente faciliti pentru dezvoltarea unor programe
complexe care s foloseasc arhitectura client-server. i dac i alte limbaje de
programare pot realiza acest lucru, Java se remarc prin faptul c indiferent de
platforma desktop pe care ruleaz aplicaia creat, aceasta va rula fr probleme.
Acest lucru se datoreaz, dup cum am afirmat i n capitolul 1, folosirii unei maini
virtuale, care este independent de platform i care ruleaz aplicaia creat i
compilat sub form de bytecode. Fie sistemul de operare Windows, Linux sau Mac
OS, aplicaia va avea aceai comportare i acelai stil vizual.
Concluzionnd, Limbajul Java ofer suficiente faciliti pentru crearea de
aplicaii client-server, iar n acest sens, pe lng uurina folosirii acestuia fa de
altele care au un nivel de abstractizare mai mic (precum C/C++), limbajul se
dovedete ca fiind unul dintre cele mai puternice.

52

5. Bibliografie
Cri:
1. BHAVE, Mahesh P., PATEKAR, Sunil A., Programming with JAVA, Pearson
Education India, 2008
2. FREEMAN, Elisabeth, FREEMAN, Eric, BATES, Bert, SIERRA, Kathy, ROBSON,
Elisabeth, Head First Design Patterns, O'Reilly Media, Inc., 2004
3. HAROLD, Eliotte Rusty, Java Network Programming, 3rd Edition, Oreilly
Media, Inc., 2004
4. LINDLEY, Craig A., Digital Audio with Java, Prentice Hall PTR, 1999
5. TOPLEY, Kim, Core Swing: Advanced Programming, Pearson Education, 1999

Articole Web:
1. Free Java Guide, History of Java programming language,
http://www.freejavaguide.com/history.html, 16/04/2013
2. Wikipedia, The Free Encyclopedia, Java (programming language),
http://en.wikipedia.org/wiki/Java_(programming_language), 16/04/2013
3. Wikipedia, The Free Encyclopedia, Just-in-time compilation,
http://en.wikipedia.org/wiki/Just-in-time_compilation, 16/04/2013
4. Wikipedia, The Free Encyclopedia, Client-server model,
https://en.wikipedia.org/wiki/Client-server_model, 20/04/2013

53

S-ar putea să vă placă și