|
Universitatea POLITEHNICA din Bucuresti Facultatea de Electronica,
Telecomunicatii si Tehnologia Informatiei . |
2011 |
|
|
22/03/2012 |
(TPI) |
2012 |
In aceasta lucrare de laborator vor fi acoperite urmatoarele probleme:
- Lucrul cu fire de executie programe multifilare
- Lucrul cu socket-uri flux (TCP) vezi si Lab. an V
- Programe de lucru cu clienti si
servere TCP vezi si Lab.4 An II, Lab.5 An II, Lab.6 An II (2007)
- Programarea pe platforma Nokia Qt SDK folosind Qt
Creator IDE
- Anexe
Atentie: La inceputul laboratoarelor stergeti mai intai toate
proiectele existente (click dreapta pe
nodul
proiectului in fereastra Projects si selectati Delete,
si confirmati ca doriti sa fie sterse
sursele in cazul proiectelor Java). La
finalul laboratoarelor stergeti proiectele create.
Programele de
calcul simple sunt secventiale,
fiecare avand un inceput, o secventa de
executii si un sfarsit, iar in orice moment pe durata rularii lui existand un singur punct de executie.
Un fir de executie (thread) este similar unui program
secvential, avand inceput, secventa de
executii si sfarsit, iar in orice moment al rularii lui exista un singur punct de executie.
Totusi, un fir nu este el insusi un program, deoarece nu poate fi executat de sine statator. In schimb, firul este executat (ruleaza) intr-un program. Posibilitatea utilizarii mai multor fire de executie intr-un singur
program este numita multithreading.
Un navigator (browser) Web este un exemplu de aplicatie multi-filara (multithreaded).
In browser se poate parcurge
pagina in timpul descarcarii unei miniaplicatii Java (applet), etc. JVM (Java Virtual Machine), permite aplicatiilor sa aiba mai multe fire
de executie in paralel.
Pentru a crea un nou fir de executie exista doua modalitati.
1. Se poate declara o
clasa ca subclasa a clasei Thread
, subclasa care trebuie sa rescrie codul (override)
metodei run
()
a clasei Thread
(care nu contine nici un cod), noul fir de executie fiind creat prin
alocarea si lansarea unei instante a subclasei.
Formatul pentru crearea unei subclase care extinde clasa Thread
si ii
reimplementeaza metoda run
()
este urmatorul:
class FirT extends Thread { public void run() { // codul firului de executie } } |
Formatul pentru crearea unei instante a subclasei este urmatorul:
FirT fir = new FirT(); |
2. Se poate declara o clasa care implementeaza interfata Runnable
, interfata care contine doar declaratia unei
metode run
()
, noul fir de executie fiind creat prin alocarea unei instante a noii clase,
pasarea acestei instante ca parametru al constructorului, la crearea unei
instante a clasei Thread
, si lansarea acelei instante a clasei Thread
.
Formatul pentru crearea unei clase care implementeaza interfata Runnable
si ii
implementeaza metoda run()
este urmatorul:
class FirR implements Runnable { public void run() { // codul firului de executie } } |
Formatul pentru crearea unei instante a noii clase si apoi a unei instante a clasei Thread
este urmatorul:
FirR r = new FirR(); Thread fir = new Thread(r); |
In ambele cazuri formatul pentru lansarea noului fir de
executie, este urmatorul:
fir.start(); // se executa fir.run(); |
Urmatorul program va fi folosit pentru a
ilustra lucrul cu fire de executie. Clasa FirSimplu extinde clasa Thread, iar metoda principala lanseaza metoda run() ca nou fir de
executie.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public
class FirSimplu extends Thread { // obiectele
din clasa curenta sunt thread-uri public FirSimplu(String str) { super(str); // invocarea constructorului
Thread(String) } // al superclasei Thread public
void run() { // metoda principala a
thread-ului curent for
(int i = 0; i < 5; i++) {
System.out.println(i + " " + getName()); // obtinerea numelui thread-ului try {
sleep((long)(Math.random()
* 1000)); // thread-ul doarme 0...1 secunda
} catch (InterruptedException e) {} }
System.out.println("Gata!
" + getName()); // obtinerea numelui thread-ului } public
static void main (String[]
args) { new FirSimplu("Unu").start(); // lansarea
thread-ului (apeleaza run()) } } |
Rezultatul executiei programului:
Clasa DemoDouaFire lanseaza doua fire de
executie de tip FirSimplu
executate concurent.
1 2 3 4 5 6 |
public
class DemoDouaFire { public
static void main (String[]
args) { new
FirSimplu("Unu").start(); // lansarea
primului thread new
FirSimplu("Doi").start(); // lansarea
celui de-al doilea thread } } |
Firele au evolutii diferite, in functie de durata intarzierii introdusa in
linia de cod:
sleep((long)(Math.random()
* 1000));
a programului FirSimplu.
Rezultatele a doua executii succesive:
Socket-ul este punctul final al unei comunicatii intre
procese. El ofera un
punct de acces la servicii de nivel transport (TCP sau UDP) in Internet.
Java ofera socket-urile ca parte a
unei biblioteci de clase standard, java.net.
Adresa socket intr-o
retea bazata pe IP consta din doua parti:
- adresa
IP, pe 32 biti (4 octeti),
reprezentata ca sir de 4 valori intre 0 si 255 despartite prin puncte (ex. 206.26.48.100) are ca alias numele
masinii si domeniului (ex. java.sun.com),
- numarul de port, pe 16 biti (2 octeti), distinct pentru
fiecare tip de protocol (TCP si UDP)
Clasa InetAddress incapsuleaza o adresa IP intr-un obiect care poate furniza informatia utila (prin invocarea metodelor obiectelor acestei clase). Clasa InetAddress nu are constructor public. De aceea, pentru a crea obiecte ale acestei clase trebuie invocata una dintre metodele de clasa getByAddress() si getByName().
O adresa IP speciala este adresa IP loopback (tot ce este trimis catre aceasta adresa IP se intoarce si devine intrare IP pentru gazda locala), cu ajutorul careia pot fi testate local programe care utilizeaza socket-uri. Pentru a identifica adresa IP loopback sunt folosite numele "localhost" si valoarea numerica "127.0.0.1". Pentru a obtine InetAddress care incapsuleaza adresa IP loopback pot fi folosite apelurile:
|
InetAddress.getByName(null) InetAddress.getByName("localhost") InetAddress.getByName("127.0.0.1") |
Urmatoarele clase Java sunt implicate in
realizarea conexiunilor TCP obisnuite.
Clasa ServerSocket reprezinta socket-ul (aflat eventual pe un
server bazat pe TCP) care asteapta si
accepta cereri de conexiune (eventual de la un client bazat pe TCP).
Clasa Socket reprezinta punctul terminal al unei
conexiuni TCP intre doua masini (eventual un client si un server).
Secventa tipica a mesajelor schimbate intre client si server este urmatoarea:
Clientul (sau, mai
general, masina conector) creeaza un punct terminal Socket in momentul in care
cererea sa de conexiune este lansata si acceptata.
Serverul (sau, mai
general, masina acceptor) creeaza un Socket in momentul in care
primeste si accepta o cerere de conexiune, si
continua sa asculte si sa astepte alte cereri pe ServerSocket.
Odata conexiunea stabilita, prin apelul metodelor getInputStream() si getOutputStream() ale clasei Socket sunt obtinute fluxuri de octeti, folosite apoi pentru comunicatia
intre aplicatii.
Secventa tipica pentru crearea socket-ului unei aplicatii conector (client):
1 2 3 4 5 6 7 8 |
// Stabilirea adresei
serverului String adresaServer = "localhost"; // Stabilirea portului serverului int portServer = 2000; // Crearea socketului (implicit este
realizata conexiunea cu serverul) Socket socketTCPClient = new Socket(adresaServer,
portServer); |
Dupa utilizare, socket-ul este inchis. Secventa tipica pentru inchiderea socket-ului:
1 2 |
// Inchiderea socketului (implicit a
fluxurilor TCP) socketTCPClient.close(); |
Secventa tipica pentru crearea socket-ului
server al unei aplicatii acceptor (server):
1 2 3 4 5 |
// Stabilirea portului serverului int portServer
= 2000; // Crearea socketului server (care accepta
conexiunile) ServerSocket
serverTCP = new ServerSocket(portServer);
|
Secventa tipica pentru crearea socket-ului
pentru tratarea conexiunii TCP cu un client:
1 2 3 |
// Blocare in asteptarea cererii de
conexiune - in momentul acceptarii // cererii se creaza socketul care
serveste conexiunea Socket conexiuneTCP = serverTCP.accept();
|
Secventa tipica pentru crearea fluxurilor de octeti asociate socket-ului (detalii fluxuri IO):
1 2 3 4 5 6 7 8 9 10 11 |
//
Obtinerea fluxului de intrare octeti TCP
InputStream inTCP = socketTCPClient.getInputStream(); //
Obtinerea fluxului scanner de caractere dinspre retea Scanner scanTCP = new Scanner(inTCP); //
Obtinerea fluxului de iesire octeti TCP
OutputStream outTCP = socketTCPClient.getOutputStream(); //
Obtinerea fluxului de iesire spre retea (similar consolei de iesire) PrintStream printTCP = new PrintStream(outTCP); |
Secventa tipica pentru trimiterea de date:
1 2 3 4 5 6 |
// Crearea unui mesaj String mesajDeTrimis = "Continut
mesaj"; // Scrierea catre retea (trimiterea
mesajului) si fortarea trimiterii printTCP.println(mesajDeTrimis); printTCP.flush(); |
Secventa tipica pentru primirea de date:
1 2 3 4 5 |
//
Citirea dinspre retea (receptia unui mesaj) String
mesajPrimit = scanTCP.nextLine(); //
Afisarea mesajului primit
System.out.println(mesajPrimit); |
Clasa urmatoare (Orar) ofera "servicii" ("obtinere
orar pentru o zi data" prin intermediul apelului getOrar(), si respectiv "modificare
orar pentru o zi data" prin intermediul apelului setOrar()) accesibile
atat local cat si la distanta (prin intermediul unui server
TCP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package pachetorar; public
class Orar { private String[] orar; // camp ascuns (starea obiectului) public Orar()
{ orar =
new String[7]; // alocarea dinamica a
spatiului pentru tablou // popularea tabloului cu valori orar[0] = "Luni este curs TPI la
seriile D si E " + "si
laborator TPI la seria E."; orar[1]
= "Marti nu sunt ore de TPI."; orar[2] = "Miercuri este
laborator TPI la seriile D si E."; orar[3] = "Joi este laborator
TPI la seria D."; orar[4] = "Vineri este laborator
TPI la seria D."; orar[5] = "Sambata nu sunt ore
de TPI."; orar[6] = "Duminica nu sunt ore
de TPI."; } public String
getOrar(int
zi) { // metoda accesor - getter return orar[zi]; // returneaza un element al tabloului } public void setOrar(int zi,
String text) { // metoda accesor -
setter orar[zi] = text; // inlocuieste un element } } |
In laborator: 1. Se deschide NetBeans IDE. 2. Se sterg toate proiectele anterior deschise, cu click dreapta in
fereastra Projects pe nodul fiecarui proiectul, selectand apoi Delete,
si confirmand ca doriti sa fie sterse
sursele (in cazul proiectelor Java). |
In laborator: 3. Se creaza un nou proiect cu File > New Project... (sau Ctrl-Shift-N). 4. In zona Categories se
selecteaza Java, in zona Projects se selecteaza Java
Class Library, se apasa Next. 5. La Project Name se scrie numele ales
pentru noul proiect, ClientServerTCP,
la Project
Location se selecteaza subdirectorul corespunzator serie, grupei si
subgrupei proprii (calea va fi de genul: D:\TPI\seriaD\434\pare). |
In laborator: 6. Se adauga
un nou fisier sursa cu File > New File... (sau Ctrl- N). 7. In zona Categories se selecteaza Java
si in zona FileTypes se selecteaza Java Class, se apasa Next. 8. In zona.in zona Class
Name se scrie numele Orar, in zona Package se scrie numele
pachetorar. 9. Se inlocuieste codul generat automat cu codul de mai sus. 10. Optional: poate fi compilat
fisierul sursa nou creat cu right
click pe nodul Orar.java (sub
nodul proiectorar, sub nodul Source
Packages al proiectului ClientServerTCP)
selectand Compile File (sau direct apasand F9) si pot fi corectate eventualele erori (provocate de greseli de
editare). |
Urmatoarea clasa (TestLocal) permite testarea locala a clasei Orar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package pachetorar; public class
TestLocal { private static Orar orar = new Orar(); public static void main(String[]
args) { // ziua folosita pentru a
testa "serviciile" obtinere/modificare
orar int
zi = 1; //
utilizarea "serviciului" de obtinere
a orarului pentru o zi data String
rezultat = orar.getOrar(zi); System.out.println("Inainte de modificare: " + rezultat); //
textul folosit pentru "serviciul" modificare orar pentru o zi data String
modificare = "Marti este curs de TPI la seria D."; //
utilizarea "serviciului" de modificare
a orarului pentru o zi data orar.setOrar(zi,
modificare); //
utilizarea "serviciului" de obtinere
a orarului pentru o zi data rezultat
= orar.getOrar(zi);
System.out.println("Dupa modificare: " + rezultat); } } |
In laborator: 1. In proiectul ClientServerTCP se adauga un
nou fisier sursa cu File > New File... (Ctrl-
N), cu numele TestLocal, in pachetul pachetorar. 2. Se inlocuieste codul generat automat cu codul de mai sus. 3. Se selecteaza Build
pe nodul de proiect al proiectului ClientServerTCP. 4. Se selecteaza Run
File pe nodul clasei cu
numele TestLocal. |
In fereastra Output a
mediului NetBeans IDE se va afisa:
Inainte de modificare: Marti nu sunt ore de
TPI. Dupa modificare: Marti este curs de TPI la
seria D. |
Clasa server care urmeaza permite accesul mai multor clienti in acelasi
timp la "serviciile" oferite de obiectele din clasa Orar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package pachetorar; import java.net.*; import java.io.*; import
java.util.Scanner; import javax.swing.JOptionPane; public class ServerMultifilarTCP1
extends Thread { private
Scanner scanTCP; private
PrintStream printTCP; private
Socket socketTCP; private static Orar orar = new Orar(); public ServerMultifilarTCP1(Socket
conexiuneTCP) throws IOException {
this.socketTCP = conexiuneTCP;
// Obtinere socket this.scanTCP = new
Scanner(socketTCP.getInputStream()); this.printTCP = new
PrintStream(socketTCP.getOutputStream()); } public void run() {
String mesaj; int
zi; try
{ while(true) { if (scanTCP.hasNextLine()) { mesaj =
scanTCP.nextLine(); if (mesaj.equals("getOrar")) { try { zi =
Integer.parseInt(scanTCP.nextLine()); JOptionPane.showMessageDialog(null,
"Server: am primit " + mesaj + " si " +
zi);
String rezultat =
orar.getOrar(zi); printTCP.println(rezultat); } catch (NumberFormatException
ex) { printTCP.println("Stop"); break; }
} /*
else if
(mesaj.equals("setOrar")) {
}
*/ else {
printTCP.println("Stop"); break;
}
}
}
socketTCP.close(); //
Inchiderea socketului si a fluxurilor
JOptionPane.showMessageDialog(null, "Server: Bye!"); } catch
(IOException ex) {
ex.printStackTrace(); } } public static void main(String[]
args) throws IOException { int
portTCP = Integer.parseInt(JOptionPane.showInputDialog( "Server:
introduceti numarul de port al serverului"));
ServerSocket serverTCP = new ServerSocket(portTCP); // Creare socket
server while (true) { Socket conexiune =
serverTCP.accept(); ServerMultifilarTCP1 server = new
ServerMultifilarTCP1(conexiune); server.start(); } } } |
Relatia intre clasele de mai sus este ilustrata in diagrama UML urmatoare:
In laborator: 1. In proiectul ClientServerTCP se adauga un nou
fisier sursa cu File > New File... (Ctrl-
N), cu numele ServerMultifilarTCP1, in pachetul pachetorar. 2. Se inlocuieste codul generat automat cu codul de mai sus. 3. Optional: poate fi compilat
fisierul sursa nou creat cu right
click pe nodul ServerMultifilarTCP1.java selectand Compile
File (sau direct apasand F9) si pot fi
corectate eventualele erori (provocate de greseli de editare). |
Clasa client care urmeaza (ClientTCP1) permite utilizatorilor accesul la distanta la serviciul "obtinere
orar pentru o zi data" oferit
de un obiect din clasa Orar aflat pe aceeasi masina cu serverul
TCP anterior.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
package pachetorar; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.net.*; import java.io.*; import java.util.*; public class ClientTCP1 { private
Scanner scanTCP; private
PrintStream printTCP; private
Socket socketTCP; private
int portTCP; private
InetAddress adresaIP; private
JFrame frame; public ClientTCP1() throws IOException
{ this.portTCP =
Integer.parseInt(JOptionPane.showInputDialog( "Client: introduceti
numarul de port al serverului"));
this.adresaIP = InetAddress.getByName(JOptionPane.showInputDialog(
"Client: introduceti adresa serverului"));
this.socketTCP = new Socket(adresaIP, portTCP); // Creare socket this.scanTCP = new
Scanner(socketTCP.getInputStream());
this.printTCP = new PrintStream(socketTCP.getOutputStream()); JFrame frame = new
JFrame("Client TCP");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container containerCurent =
frame.getContentPane();
containerCurent.setLayout(new BorderLayout()); JPanel pane = new JPanel(new
GridLayout(0, 1)); final JLabel eticheta = new JLabel("Orarul
zilei de:"); pane.add(eticheta); final int numButtons = 8; final
JRadioButton[] radioButtons = new JRadioButton[numButtons]; final ButtonGroup group = new ButtonGroup(); radioButtons[0] = new
JRadioButton("Luni");
radioButtons[0].setActionCommand("0"); radioButtons[1] = new
JRadioButton("Marti");
radioButtons[1].setActionCommand("1");
radioButtons[2] = new JRadioButton("Miercuri");
radioButtons[2].setActionCommand("2");
radioButtons[3] = new JRadioButton("Joi"); radioButtons[3].setActionCommand("3");
radioButtons[4] = new JRadioButton("Vineri");
radioButtons[4].setActionCommand("4");
radioButtons[5] = new JRadioButton("Sambata");
radioButtons[5].setActionCommand("5"); radioButtons[6]
= new JRadioButton("Duminica");
radioButtons[6].setActionCommand("6");
radioButtons[7] = new JRadioButton("Stop");
radioButtons[7].setActionCommand("Stop");
radioButtons[0].setSelected(true);
for
(int i = 0; i < numButtons; i++) {
group.add(radioButtons[i]);
pane.add(radioButtons[i]); }
containerCurent.add(pane, BorderLayout.WEST); JButton sendButton = new JButton("Trimite"); sendButton.addActionListener(new ActionListener()
{ // trimiterea catre server a
cererii de efectuare a serviciului public void actionPerformed(ActionEvent e) { String service = "getOrar"; printTCP.println(service); String command = group.getSelection().getActionCommand(); printTCP.println(command);
} });
containerCurent.add(sendButton, BorderLayout.NORTH); final JTextArea outGrafic = new
JTextArea(8, 40); // Zona non-editabila
JScrollPane scrollPane = new JScrollPane(outGrafic,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
outGrafic.setEditable(false);
containerCurent.add(outGrafic, BorderLayout.CENTER);
frame.pack(); frame.setVisible(true);
String mesaj; while(true) { // afisarea
raspunsului primit de la server
if (scanTCP.hasNextLine()) { mesaj = scanTCP.nextLine(); outGrafic.setText(outGrafic.getText()
+ mesaj +
"\n"); if
(mesaj.equals("Stop")) System.exit(0); // Conditie oprire } } } public
static void main(String[]
args) throws IOException {
ClientTCP1 client = new ClientTCP1(); } } |
Diagrama UML urmatoare reflecta codul de mai sus:
In laborator: 1. In proiectul ClientServerTCP se adauga un
nou fisier sursa cu File > New File... (Ctrl-
N), cu numele ClientTCP1, in pachetul pachetorar. 2. Se inlocuieste codul generat automat cu codul de mai sus. |
In laborator: 1. Se selecteaza Build
pe nodul de proiect al proiectului ClientServerTCP. 2. Se selecteaza Run
File pe nodul clasei cu
numele ServerMultifilarTCP1. 3. Cand este afisata fereastra de dialog in care scrie Server: introduceti numarul
de port al serverului se introduce
valoarea 3000 pentru portul pe care asculta
serverul TCP. |
In laborator: 1. Se selecteaza Run
File pe nodul clasei cu
numele ClientTCP1. 2. Se introduce valoarea 3000 pentru
portul serverului si se introduce adresa IP a calculatorului pe care a
fost lansat serverul, sau se apasa Cancel (generandu-se astfel adresa loopback localhost). |
In laborator: 1. Se utilizeaza interfata clientului. Pentru oprire se selecteaza Stop si se
apasa Trimite. |
Clasa client care urmeaza (ClientTCP2) permite accesul la distanta la serviciul "modificare orar
pentru o zi data" oferit de un
obiect din clasa Orar aflat pe aceeasi masina cu serverul
TCP anterior.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 00 01 02 |
package pachetorar; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.net.*; import java.io.*; import java.util.*; public class ClientTCP2 { private
Scanner scanTCP; private
PrintStream printTCP; private
Socket socketTCP; private
int portTCP; private
InetAddress adresaIP; private
JFrame frame; public ClientTCP2() throws IOException
{
this.portTCP = Integer.parseInt(JOptionPane.showInputDialog( "Client:
introduceti numarul de port al serverului")); this.adresaIP =
InetAddress.getByName(JOptionPane.showInputDialog( "Client: introduceti
adresa serverului"));
this.socketTCP = new Socket(adresaIP, portTCP); // Creare socket this.scanTCP = new Scanner(socketTCP.getInputStream()); this.printTCP = new
PrintStream(socketTCP.getOutputStream()); JFrame frame = new JFrame("Client
TCP");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container containerCurent = frame.getContentPane();
containerCurent.setLayout(new BorderLayout());
JPanel pane = new JPanel(new GridLayout(0, 1));
final JLabel eticheta = new JLabel("Modificarea orarului zilei
de:");
pane.add(eticheta);
final int numButtons = 8;
final JRadioButton[] radioButtons = new JRadioButton[numButtons];
final ButtonGroup group = new ButtonGroup();
radioButtons[0] = new JRadioButton("Luni");
radioButtons[0].setActionCommand("0");
radioButtons[1] = new JRadioButton("Marti");
radioButtons[1].setActionCommand("1"); radioButtons[2] = new
JRadioButton("Miercuri");
radioButtons[2].setActionCommand("2");
radioButtons[3] = new JRadioButton("Joi");
radioButtons[3].setActionCommand("3");
radioButtons[4] = new JRadioButton("Vineri"); radioButtons[4].setActionCommand("4");
radioButtons[5] = new JRadioButton("Sambata");
radioButtons[5].setActionCommand("5");
radioButtons[6] = new JRadioButton("Duminica");
radioButtons[6].setActionCommand("6"); radioButtons[7]
= new JRadioButton("Stop");
radioButtons[7].setActionCommand("Stop");
radioButtons[0].setSelected(true); for
(int i = 0; i < numButtons; i++) {
group.add(radioButtons[i]); pane.add(radioButtons[i]); }
containerCurent.add(pane, BorderLayout.WEST);
final JTextField inTextGrafic = new JTextField(40); //
containerCurent.add(inTextGrafic, BorderLayout.SOUTH); JButton sendButton = new
JButton("Trimite"); sendButton.addActionListener(new
ActionListener() { // trimiterea catre server a
cererii de efectuare a serviciului public void actionPerformed(ActionEvent e) { String service = "setOrar"; printTCP.println(service); String command =
group.getSelection().getActionCommand(); printTCP.println(command);
printTCP.println(inTextGrafic.getText());
inTextGrafic.setText("");
} });
containerCurent.add(sendButton, BorderLayout.NORTH);
final JTextArea outGrafic = new JTextArea(8, 40); // Zona
non-editabila
JScrollPane scrollPane = new JScrollPane(outGrafic,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
outGrafic.setEditable(false);
containerCurent.add(outGrafic, BorderLayout.CENTER); inTextGrafic.requestFocus(); // Cerere focus
pe intrarea de text
frame.pack();
frame.setVisible(true);
String mesaj; while(true) { // afisarea
raspunsului primit de la server if (scanTCP.hasNextLine()) { mesaj = scanTCP.nextLine();
outGrafic.setText(outGrafic.getText() + mesaj + "\n"); if
(mesaj.equals("Stop")) System.exit(0); // Conditie oprire } } } public static
void main(String[] args) throws IOException {
ClientTCP2 client = new ClientTCP2(); } } |
In laborator: 1. In proiectul ClientServerTCP se adauga un
nou fisier sursa cu File > New File... (Ctrl-
N), cu numele ClientTCP2, in pachetul pachetorar. 2. Se inlocuieste codul generat automat cu codul de mai sus. |
In laborator: 1. Se selecteaza Build
pe nodul de proiect al proiectului ClientServerTCP. 2. Se selecteaza Run
File pe nodul clasei cu
numele ServerMultifilarTCP1. 3. Cand este afisata fereastra de dialog in care scrie Server: introduceti numarul
de port al serverului se introduce
valoarea 5000 pentru portul pe care asculta
serverul TCP. |
In laborator: 1. Se selecteaza Run
File pe nodul clasei cu
numele ClientTCP1. 2. Se introduce valoarea 5000 pentru
portul serverului si se introduce adresa IP a calculatorului pe care a
fost lansat serverul, sau se apasa Cancel (generandu-se astfel adresa localhost). |
In laborator: 1. Se selecteaza Run
File pe nodul clasei cu
numele ClientTCP2. 2. Se introduce valoarea 5000 pentru
portul serverului si se introduce adresa IP a calculatorului pe care a
fost lansat serverul, sau se apasa Cancel (generandu-se astfel adresa
localhost). |
In laborator: 1. Se utilizeaza interfata clientului. Pentru oprire se selecteaza Stop si se
apasa Trimite. |
Se observa ca al doilea client
nu poate cu adevarat modifica orarul. Acest lucru se intampla deoarece in codul
serverului nu este implementata portiunea necesara accesului la serviciul "modificare
orar pentru o zi data" oferit de un obiect din
clasa Orar.
In laborator: 1. Se completeaza
codul clasei ServerMultifilarTCP1 pentru a putea oferi si serviciul de modificare a orarului
(prin apelul la metoda setOrar()). 2. Se reiau pasii necesari
executiei ServerMultifilarTCP1, ClientTCP1 si ClientTCP2. 3. Se utilizeaza interfetele clientilor, testand corectitudinea
implementarii. |
Asa trebuie sa arate interfata ClientTCP1 dupa modificarile cerute si utilizarea unui client
de tip ClientTCP1 si a unuia de tip ClientTCP2 (prin intermediul
caruia orarul zilei de sambata a fost
modificat in "Recuperare ore pierdute"):
Optional (pentru
bonus): 1. Se adauga in
codul clasei Orar un flag (variabila de tip boolean) sub forma unui nou camp cu numele editabil, initializat cu true. Se adauga si doua metode in clasa Orar: una numita setEditabil() care primeste un parametru de
tip boolean pe care il foloseste
pentru a actualiza valoarea campului editabil, si una numita getEditabil() care returneaza valoarea campului editabil. 2. Se completeaza
codul clasei ServerMultifilarTCP1 pentru a putea oferi si serviciile de obtinere si de
modificare a flagului editabil pentru obiectul de tip Orar. 3. Se creeaza un
nou client, pornind de la codurile claselor ClientTCP1 si ClientTCP2, care permite obtinerea la distanta a valorii
flagului si ofera utilizatorului posibilitatea
modificarii lui. 4. Se utilizeaza interfetele clientilor, testand corectitudinea
implementarii. |
Eventual si:
\
Fiecare grup de 2
studenti ai unei subgrupe (cei 2 studenti care lucreaza la acelasi
calculator in cadrul laboratorului)
- isi
va alege o clasa din urmatoarea lista de clase (sau o alta clasa auto-propusa):
PC |
Laptop |
Proiector |
Smartphone |
Carte |
Masina |
TV |
Copiator |
ConsolaJocuri |
CameraVideo |
Bicicleta |
Reportofon |
DVDPlayer |
Imprimanta |
- va crea codul clasei alese, dupa modelul clasei Orar de mai sus, adica va avea
- cel putin un camp (atribut) ascuns (private),
- cel putin o metoda care sa permita obtinerea valorii unui camp,
- cel putin o metoda care sa permita modificarea valorii unui camp.
- va adapta codurile claselor ClientTCP1, ClientTCP2 si ServerMultifilarTCP1
astfel incat cei doi clienti sa permita
utilizatorului:
- obtinerea la distanta a valorii campului noii clase, respectiv
- modificarea la distanta a valorii campului noii clase.
Temele vor
fi predate la lucrarea urmatoare,
cate un exemplar pentru fiecare grup de
2 studenti, pe hartie (cu numele studentilor pe prima pagina),
scrise de mana sau sub forma de listing.
Teme suplimentare pentru
data viitoare (pentru bonus) la
alegere:
1. Adaugarea altor componente grafice in interfetele clientilor (de exemplu un buton care
sa permita oprirea serverului multifilar de catre clienti).
2. Adaptarea clientilor pentru a putea deveni applet-uri.
3. Crearea unor servicii mai complexe bazate pe accesul la mai
multe campuri ale clasei alese.
1. Java Tutorials: Learning Swing with the
NetBeans IDE
(http://java.sun.com/docs/books/tutorial/uiswing/learn/index.html)
2. Java
Tutorials: How
to Use Buttons, Check Boxes, and Radio Buttons
(http://java.sun.com/docs/books/tutorial/uiswing/components/button.html)
3. Java
Tutorials: How
to Use Combo Boxes
(http://java.sun.com/docs/books/tutorial/uiswing/components/combobox.html)
4. Java
Tutorials: How
to Use Lists
(http://java.sun.com/docs/books/tutorial/uiswing/components/list.html)