ConexiuneRetea
Dupa cum am mai spus, rolul acestei clase este de a intermedia conexiunile. Ea are urmatorii 3 membri privati: - conexiune (Socket) - scannerTCP (Scanner) - printerTCP (PrintStream) Socket-ul (conexiune) reprezinta efectiv conexiunea care are loc intre client si server. Practic Socket-ul este ca un fir prin care se transmite informatia, de la o sursa catre o adresa. In exemplul current folosim adrese de IP cu TCP (Transmition Control Protocol). Pentru a putea opera pe acest socket, avem nevoie de doua operatii de baza: scrierea de informatii pe socket si citirea de informatii de pe socket. Pentru aceasta, vom folosi Scanner (citire) si PrintStream (scriere). Constructorul acestei clase initializeaza o conexiune pe baza unui socket primit ca parametru in constructor. Cele doua metode (getLocalAddress si getRemoteAddress) ne furnizeaza informatii despre adresa locala si adresa destinatie a conexiunii. Adresa locala este cea a calculatorului care a initiat conexiunea. Adresa remote este cea a serverului. Metodele nextLine si printLine(String) se folosesc pentru a citi urmatoarele informatii pregatite de conexiunea respectiva pentru a trimite mesaje pe conexiune. Practic nextLine este echivalentul lui read, iar printLine este echivalentul pentru write. Scrierea si citirea de pe socketuri abstractizeaza cu success modelul de baza 2
al scrierii si citirii in java. In concluzie, rolul acestei clase este de a trimite si primi mesaje de pe o conexiune.
DialogUtilizator
Rolul acestei clase este de a intermedia comunicatia cu utlizatorul, prezentandu-I interfata grafica. Interfata grafica este compusa din: - o caseta de text unde apar mesajele (atat cele de la client cat si la server) - o caseta de text unde se introduc mesajele care se trimit - butonul de BYE (bonus) Intrucat responsabilitatea comunicatiei nu apartine acestei clase, ci a clasei ConexiuneRetea, clasa DialogUtilizator are o metoda setConexiune(Socket) In interiorul constructorului se creeaza toate elemente grafice ale ferestrei. Aceasta clasa extinde JFrame pentru a putea afisa o fereastra. Se declara control cu control, iar apoi se adauga la container. Layout-ul containerului este de tip BorderLayout. Metodele nextLine si printLine nu au ca rol comunicatia cu socket-ul (cum era la clasa ConexiuneRetea). In schimb, aceste metode sunt chemate din clasele ServerChatN2N si ClientChatN2N. Asadar, in aceasta clasa aceste doua metode au ca rol interactiunea cu casetele de text (scriere si citire din casetele de text). Clasa locala AscultatorText implementeaza ActionListener. Metoda actionPerformed este chemata atunci cand se apasa tasta enter. In acel moment, textul scris in caseta de text este trimis catre Client sau Server, care mai departe, cu ajutorul lui ConexiuneRetea se trimite pe retea prin Socket.
ServerChatN2N
Clasa ServerChatN2N reprezinta serverul. Acesta se foloseste de un DialogUtilizator, de un vector de conexiuni si de un socket de server (pentru a putea sta in starea de Listen). In momentul rularii (metoda main), acesta cere numarul de port de care va asculta. Este necesar ca sa nu mai fie deja folosit, intrucat o eroare va fi afisata (exceptii bonus). Dupa crearea socketului in stare de ascultare, se incepe o bucla infinita unde se primesc conexiuni, si pentru fiecare client care doreste sa se conecteze se adauga la vectorul de conexiuni, se construieste serverul si se ruleaza Thread-ul pe care acesta se bazeaza.. In interiorul acestui thread, daca exista mesaje care asteapta sa fie primite, se 3
primesc si se trimit la toti clientii conectati, folosind un for peste vectorul de conexiuni. Am adaugat interfata grafica si clasei ServerChatN2N astfel incat mesajele primite de server vor putea fi vazut cu textul "ClientNR" la inceput,pentru a putea sti de la ce client provin(bonus). Daca in schimb se primeste text-ul BYE, thread-ul se opreste si conexiunea se elibereaza.
ClientChatN2N
Aceasta clasa reprezinta fiecare client care se conecteaza. Se foloseste de un DialogUtilizator pentru interactiunea cu utilizatorul, de o ConexiuneRetea pentru interactiunea cu reteaua si trimiterea/primirea mesajelor. Ca si clasa ServerChatN2N, ClientChatN2N extinde clasa Thread. In constructorul acestei clase, clientului, i se citesc de la utilizator numarul de port al serverului si adresa de IP a serverului. Daca se poate efectua conexiunea, thread-ul incepe sa ruleze, ceea ce il face sa primeasca fiecare mesaj pe care ceilalti clienti il trimit serverului, si server-ul il trimite catre client. Similar cu Server-ul, daca se primeste BYE, atunci clientul se inchide.
Apoi am observat ca legatura de conexiune dintre ClientChatN2N, DialogUtilitizator si ConexiuneRetea nu era facuta bine. Astfel, am adaugat in ClientChatN2N, in constructor linia de cod: dialog.setConexiune(conexiune); si am remediat problema.
Serverul (ServerChatN2N)
Atunci cand se ruleaza server-ul apare mai intai o caseta de dialog care ne cere portul pe care va rula serverul.
In acest moment serverul este pregatit sa accepte conexiuni din partea clientilor care se conecteaza la IP-ul si portul pe care este el deschis.
Clientul (ClientChatN2N)
Atunci cand se ruleaza client-ul apare mai intai o caseta de dialog care ne cere portul pe care se va conecta clientul:
Apoi va aparea o caseta care va cere IP-ul serverului la care ne vom conecta:
Dupa ce se scrie un mesaj si se da enter, acesta apare in caseta mare de text. Acum vom mai rula inca un client, pentru a vedea cum mesajele se propaga intre clienti, cu ajutorul serverului.
Mesajul scris de clientul 2 (cel de sus) a aparut si in clientul 1(cel de jos). Practic orice mesaj scris de orice client se poate vedea imediat in oricare alt client conectat la server in acel moment si se va putea vedea si de la server avand si un nume corespunzator.