Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: http://upload.wikimedia.org/wikipedia/en/thumb/2/2e/Java_Logo.svg/322px-Java_Logo.svg.png   Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: http://hopf.chem.brandeis.edu/yanglingfa/pic/uml.GIF

 

 

 

     Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: Description: D:\_2010_Nokia\Curs Nokia-UPB 2011\ETTI_logo_bleu.jpg

Universitatea POLITEHNICA din Bucuresti

Facultatea de Electronica, Telecomunicatii si Tehnologia Informatiei

.

 

 

 

 

 

 

 

 

Laboratorul  – sala B123

 

 

20/02/2014

Tehnologii de Programare

in Internet

(TPI)

 

                     

   

 2013-2014

                                            

Laborator 2

Programarea aplicatiilor Java la nivel socket. Fire de executie. Interfete grafice Swing.

 

2.1. Descrierea laboratorului

 

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)

 

Exercitii in laborator

 

- 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

 surselein cazul proiectelor Java). La finalul laboratoarelor stergeti proiectele create.

 

 

 

2.2. Utilizarea firelor de executie (threads) in Java

 

2.2.1. Modalitati de a crea un fir de executie

 

 

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();

 

 

 

 

 

 

 

2.2.2. Programe de lucru cu fire de executie

 

 

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:      

              

 

 

 

 

 

 

 

2.3. Introducere in socket-uri Java

 

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.

 

2.3.1. Utilizarea clasei java.net.InetAddress

 

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")

 

2.3.2. Socket-uri flux (TCP) Java

 

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.

 

2.3.3. Utilizarea clasei Socket

 

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();

 

2.3.4. Utilizarea clasei ServerSocket

 

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);

 

2.4. Programe de lucru cu socket-uri – clienti si servere

2.4.1. Clasa care ofera un serviciu local sau la distanta

 

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.

 

 

 

2.4.2. Clasa server multifilar

 

 

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).

 

2.4.3. Clienti pentru serverul multifilar

 

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); // Camp editabil intrare

        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.

 

\

2.4.4. Exercitii in laborator (sau pentru acasa)

 

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.

 

Anexa - Resurse suplimentare privind modul de lucru cu NetBeans IDE

 

1. Java Tutorials: Learning Swing with the NetBeans IDE

(http://docs.oracle.com/javase/tutorial/uiswing/learn/index.html)

2. Java Tutorials: How to Use Buttons, Check Boxes, and Radio Buttons

      (http://docs.oracle.com/javase/tutorial/uiswing/components/button.html)

3. Java Tutorials: How to Use Combo Boxes

      (http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html)

4. Java Tutorials: How to Use Lists

      (http://docs.oracle.com/javase/tutorial/uiswing/components/list.html)

etc.