Description: Description: java-cup                     Catedra de Telecomunicatii                    Description: Description: logo ETTI

 15/01/2013                  

                      Programare Orientata spre Obiecte (POO)  

 

 

 

Laborator 6

Fire de executie (threads) Java. Aplicatii multifilare bazate pe socket-uri TCP si interfete grafice Swing

 

6.1. Descrierea laboratorului

 

In aceasta lucrare de laborator vor fi acoperite urmatoarele probleme:

 

- Utilizarea firelor de executie (clasa Threads) Introducere in fire de executielink extern

 

- Aplicatii client-server cu interfata grafica Swing bazate pe socket-uri TCP

 

- Precizari privind mini-proiectul pentru examenul final

 

6.2. Utilizarea firelor de executie (threads) in Java

 

6.2.1. Modalitati de a crea un fir de executie

 

Pentru a crea un nou fir de executie (detalii privind firele de executie - threads - in Java) 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() (declaratie similara celei din clasa Thread, clasa Thread implementand interfata Runnable), noul fir fiind obtinut prin crearea unei instante a noii clase, pasata constructorului la crearea unei instante a clasei Thread, si lansarea noii 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();    

 

Variante compacte pentru crearea si lansarea noilor fire de executie:

                             

       new FirT().start();                   // nu exista variabila de tip FirT 
                                             // care sa refere explicit firul
       FirR r = new FirR();
       new Thread(r).start();                // nu exista variabila de tip Thread 
                                             // care sa refere explicit firul
       Thread fir = new Thread(new FirR());  // nu exista variabila de tip FirR
       fir.start();                          // care sa refere explicit firul                                        
       new Thread(new FirR()).start();       // nu exista variabila de tip Thread
                                             // si nici variabila de tip FirR 
                                             // care sa refere explicit firul 

 

 

6.2.2. Programe multifilare (multi-threaded)

 

Urmatorul program va fi folosit pentru a exeplifica 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())

    }

  }

 

Clasa DemoTreiFire lanseaza trei fire de executie de tip FirSimplu executate concurent.

 

1

2

3

4

5

6

7

 public class DemoTreiFire {

    public static void main (String[] args) {

        new FirSimplu("Unu").start();     // “lansarea” primului thread

        new FirSimplu("Doi").start();     // “lansarea” celui de-al doilea thread

        new FirSimplu("Trei").start();    // “lansarea” celui de-al treilea thread

    }

 }

 

 

 

 

Firele au evolutii diferite, in functie de durata intarzierii introdusa in FirSimplu de linia:

 

          sleep( (long) (Math.random() * 1000) );

 

 

 

In laborator:

1. Inchideti proiectele anterioare (Ctrl+W). Creati un nou proiect fire

2. Creati o noua clasa, numita FirSimplu, folosind codul dat mai sus.

3. Creati un obiect tip FirSimplu (cu nume "Test"), inspectati-i campurile (atributele) si metodele.

4. Tot in proiectul fire creati clasa DemoTreiFire folosind codul de mai sus. Compilati clasele.

5. Right-click pe clasa, selectati si executati main(). Urmariti efectul in Terminal Window.

 

 

 

6.3. Aplicatii client-server bazate pe socket TCP si interfete grafice Swing

6.3.1. Sistem de comunicatie client-server bazat pe socket TCP si GUI Swing

Superclasa ElementeComuneClientServer contine elemente comune clientilor si serverelor si este mostenita si extinsa de clienti si servere:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

 import java.net.*;
 import java.io.*; 
 import javax.swing.JOptionPane;  
 
 public class ElementeComuneClientServer {  
    protected ConexiuneRetea conexiune;
    protected Socket socketTCP;
    protected int portTCP;
 
    public ElementeComuneClientServer(String tip) throws IOException {
        portTCP = Integer.parseInt(JOptionPane.showInputDialog(tip + 
                         ": introduceti numarul de port al serverului"));
    }

 }

 

Clasa utilitara ConexiuneRetea incapsuleaza tratarea conexiunilor TCP:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

 import java.net.*;
 import java.io.*;
 import java.util.Scanner;
 
 public class ConexiuneRetea {
    private Socket conexiune;                
    private Scanner scannerTCP;
    private PrintStream printerTCP; 
    public ConexiuneRetea(Socket conexiune) throws IOException {                              
        this.conexiune = conexiune;
        this.scannerTCP = new Scanner(conexiune.getInputStream()); 
        this.printerTCP = new PrintStream(conexiune.getOutputStream()); 
    } 
    public String nextLine() { 
        return this.scannerTCP.nextLine();
    } 
    public int nextInt() { 
        return this.scannerTCP.nextInt();
    }
    public void printLine(String text) { 
        this.printerTCP.println(text); 
        this.printerTCP.flush();
    } 

 }

 

 

Clasa ClientBidirectionalSwing mosteneste si extinde clasa ElementeComuneClientServer:

 

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

 import java.net.*;
 import java.io.*; 
 import javax.swing.JOptionPane;  

 import java.awt.*;

 import java.awt.event.*;

 import javax.swing.*;

 

 public class ClientBidirectionalSwing extends ElementeComuneClientServer

                                       implements Runnable {   

    private InetAddress adresaIP;

    private JFrame frame;

    private JTextField inTextGrafic;   // Intrare - linie text grafica (JtextField)

    private JTextArea outTextGrafic;   // Iesire - zona text grafica (JtextArea)

    private JScrollBar vertical;

    private String sirCitit;

  

    public ClientBidirectionalSwing() throws IOException {

        super("Client");

        adresaIP = InetAddress.getByName(JOptionPane.showInputDialog(

                       "Client: introduceti adresa serverului"));

        socketTCP = new Socket(adresaIP, portTCP);           // Creare socket

        conexiune = new ConexiuneRetea(socketTCP);

       

        // Crearea obiectului cadru (frame), cu titlu specificat

        JFrame frame = new JFrame("Client bidirectional Swing"); // Stabilire titlu

        Container containerCurent = frame.getContentPane();

        containerCurent.setLayout(new BorderLayout());

 

        outTextGrafic = new JTextArea(5, 40);  // Zona text non-editabila de iesire

        JScrollPane scrollPane = new JScrollPane(outTextGrafic,

                     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,

                     JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        vertical = scrollPane.getVerticalScrollBar();

        containerCurent.add("Center", scrollPane);

        outTextGrafic.setEditable(false);

        outTextGrafic.append("Pentru oprire introduceti '.' si <Enter>\n\n");

 

        inTextGrafic = new JTextField(40);      // Camp de text editabil de intrare

        containerCurent.add("South", inTextGrafic);

        inTextGrafic.requestFocus(); // Cerere focus pe intrarea text

 

        // Inregistrare "ascultator" de "evenimente actionare" la "obiectul sursa"

        inTextGrafic.addActionListener(new AscultatorInText());

 

        // Iesire din program la inchiderea ferestrei

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

        frame.pack();      // Impachetarea (compactarea) componentelor in container

        frame.setVisible(true);      // Fereastra devine vizibila

    }

 

    // Clasa interna "ascultator" de "evenimente actionare"

    // implementeaza interfata ActionListener

    class AscultatorInText implements ActionListener {

 

      // Tratarea actionarii intrarii de text (introducerii unui "Enter")

      public void actionPerformed(ActionEvent ev) {

 

         sirCitit = inTextGrafic.getText();  // Citirea unei linii din intrarea text                 

         inTextGrafic.setText("");           // Golirea intrarii text

         conexiune.printLine(sirCitit);

 

         outTextGrafic.append("S-a introdus: "+sirCitit+"\n"); // Scriere linie

         // actualizeaza pozitia barei de defilare, varianta imbunatatita a

         // vertical.setValue(vertical.getMaximum() - vertical.getVisibleAmount());

         SwingUtilities.invokeLater(new Runnable()

           { public void run() { vertical.setValue(vertical.getMaximum()); } });  

          

         if (sirCitit.equals(new String(".")))   System.exit(0); // Conditie oprire

      }     

    }

 

    public void run () {

        String mesaj;

        while (true) {

          mesaj = conexiune.nextLine();

 

          outTextGrafic.append("S-a primit:   " + mesaj + "\n");

          // actualizeaza pozitia barei de defilare, varianta imbunatatita a

          // vertical.setValue(vertical.getMaximum() - vertical.getVisibleAmount());

          SwingUtilities.invokeLater(new Runnable()

            { public void run() { vertical.setValue(vertical.getMaximum()); } });  

           

          if (mesaj.equals(".")) break;    // Testarea conditiei de oprire

        }

        try {  socketTCP.close();        // Inchiderea socketului si a fluxurilor

        } catch (IOException ex) {}

        JOptionPane.showMessageDialog(null, "Client: Bye!");        

    }

   

    public static void main (String args[]) throws IOException {

        ClientBidirectionalSwing client = new ClientBidirectionalSwing();

        new Thread(client).start();

    }

 }

 

Clasa ServerBidirectionalSwing mosteneste si extinde clasa ElementeComuneClientServer:

 

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

 import java.net.*;
 import java.io.*; 
 import javax.swing.JOptionPane;  

 import java.awt.*;

 import java.awt.event.*;

 import javax.swing.*;

 public class ServerBidirectionalSwing extends ElementeComuneClientServer

                                       implements Runnable {   

    private ServerSocket serverTCP;

    private JFrame frame;

    private JTextField inTextGrafic;   // Intrare - linie text grafica (JtextField)

    private JTextArea outTextGrafic;   // Iesire - zona text grafica (JtextArea)

    private JScrollBar vertical;

    private String sirCitit;

  

    public ServerBidirectionalSwing() throws IOException {

        super("Server");

        serverTCP = new ServerSocket(portTCP);              // Creare socket server

        socketTCP = serverTCP.accept();                     // Creare socket

        conexiune = new ConexiuneRetea(socketTCP);

       

        // Crearea obiectului cadru (frame), cu titlu specificat

        JFrame frame = new JFrame("Server bidirectional Swing"); // Stabilire titlu

        Container containerCurent = frame.getContentPane();

        containerCurent.setLayout(new BorderLayout());

 

        outTextGrafic = new JTextArea(5, 40);  // Zona text non-editabila de iesire

        JScrollPane scrollPane = new JScrollPane(outTextGrafic,

                     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,

                     JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        vertical = scrollPane.getVerticalScrollBar();

        containerCurent.add("Center", scrollPane);

        outTextGrafic.setEditable(false);

        outTextGrafic.append("Pentru oprire introduceti '.' si <Enter>\n\n");

 

        inTextGrafic = new JTextField(40);      // Camp de text editabil de intrare

        containerCurent.add("South", inTextGrafic);

        inTextGrafic.requestFocus(); // Cerere focus pe intrarea text

 

        // Inregistrare "ascultator" de "evenimente actionare" la "obiectul sursa"

        inTextGrafic.addActionListener(new AscultatorInText());

 

        // Iesire din program la inchiderea ferestrei

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.pack();      // Impachetarea (compactarea) componentelor in container

        frame.setVisible(true);      // Fereastra devine vizibila

    }

 

    // Clasa interna "ascultator" de "evenimente actionare"

    // implementeaza interfata ActionListener

    class AscultatorInText implements ActionListener {

 

      // Tratarea actionarii intrarii de text (introducerii unui "Enter")

      public void actionPerformed(ActionEvent ev) {

 

         sirCitit = inTextGrafic.getText();  // Citirea unei linii din intrarea text                  

         inTextGrafic.setText("");           // Golirea intrarii text

         conexiune.printLine(sirCitit);

 

         outTextGrafic.append("S-a introdus: "+sirCitit+"\n"); // Scriere linie

 

         // actualizeaza pozitia barei de defilare, varianta imbunatatita a

         // vertical.setValue(vertical.getMaximum() - vertical.getVisibleAmount());

         SwingUtilities.invokeLater(new Runnable()

           { public void run() { vertical.setValue(vertical.getMaximum()); } });  

           

         if (sirCitit.equals(new String(".")))   System.exit(0); // Conditie oprire

      }     

    }

   

    public void run () {

        String mesaj;

        while (true) {

          mesaj = conexiune.nextLine();

 

          outTextGrafic.append("S-a primit:   " + mesaj + "\n");

          // actualizeaza pozitia barei de defilare, varianta imbunatatita a

          // vertical.setValue(vertical.getMaximum() - vertical.getVisibleAmount());

          SwingUtilities.invokeLater(new Runnable()

            { public void run() { vertical.setValue(vertical.getMaximum()); } });  

           

          if (mesaj.equals(".")) break;    // Testarea conditiei de oprire

        }

        try {  socketTCP.close();        // Inchiderea socketului si a fluxurilor

        } catch (IOException ex) {}

        JOptionPane.showMessageDialog(null, "Server: Bye!");        

    }

 

    public static void main (String args[]) throws IOException {

        ServerBidirectionalSwing server = new ServerBidirectionalSwing();

        new Thread(server).start();

    }

 }

 

 

Description: Description: 

 

Nu uitati: Daca bara de stare a executiei este activa () verificati cu Alt+Tab daca a aparut o fereastra Java (in spatele ferestrelor vizibile).

 

Nu uitati: Pentru a opri executia, right click pe  si Reset Machine (sau Ctrl+Shift+Tab).

 

 

In laborator:

1. Lansati in executie BlueJ. Inchideti proiectele anterioare. Creati un proiect socketSwing

2. In proiectul socket creati cele 4 clase ale caror coduri sunt date mai sus. Compilati codurile.

3. Testati sistemul ca la laboratorul anterior.

 

                                  

In laborator:

1. La unul dintre calculatoare right-click pe clasa ServerBidirectionalSwing.

2. Selectati si executati main(). Folositi numarul de port 3000.

 

3. La un alt calculator (daca nu aveti la dispozitie un alt calculator in retea, deschideti inca o sesiune BlueJ) right-click pe clasa ClientBidirectionalSwing, selectati si executati main().

4. Folositi adresa primului calculator, pe care se executa ServerBidirectionalSwing (adresa "localhost" in cazul in care folositi doua sesiuni BlueJ pe acelasi calculator), si numarul de port 3000.

5. Urmariti efectul la client si la server.

 


 

6.3.2. Sistem de comunicatie client-server (N-la-N) multifilar, bazat pe socket-uri TCP si interfata grafica Swing

 

 

Clasa utilitara DialogUtilizator incapsuleaza tratarea interactiunii cu utilizatorul (GUI):

 

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

import javax.swing.JOptionPane;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

 

public class DialogUtilizator extends JFrame {

    private JTextField inTextGrafic; // Intrare - linie de text grafica (JtextField)

    private JTextArea outTextGrafic;  // Iesire - zona de text grafica (JtextArea)

    private JScrollBar vertical;

    private ConexiuneRetea conexiune;

    private String sirCitit;

    String nume;

 

    // Initializari grafice

    public DialogUtilizator(String nume) {          // constructor

        super(nume);        // Stabilire titlu fereastra (JFrame)

        this.nume = nume;

        Container containerCurent = this.getContentPane();

        containerCurent.setLayout(new BorderLayout());

        // Zona de text non-editabila de iesire (cu posibilitati de defilare)

        outTextGrafic = new JTextArea(5, 40);

        JScrollPane scrollPane = new JScrollPane(outTextGrafic,

                     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,

                     JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

 

        vertical = scrollPane.getVerticalScrollBar();

        containerCurent.add("Center", scrollPane);

        outTextGrafic.setEditable(false);

        // Camp de text editabil de intrare

        inTextGrafic = new JTextField(40);

        containerCurent.add("South", inTextGrafic);

 

        // Inregistrarea "ascultatorului" de "evenimente actionare" la

        // "obiectul sursa" intrare de text

        inTextGrafic.addActionListener(new AscultatorInText());

        // Iesire din program la inchiderea ferestrei

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        pack();            // Impachetarea (compactarea) componentelor in container

        setVisible(true);            // Fereastra devine vizibila

        inTextGrafic.requestFocus(); // Cerere focus pe intrarea de text    

    }

 

    public String nextLine() {

        String linie = inTextGrafic.getText();     // Citirea unei linii text                 

        inTextGrafic.setText("");                  // Golirea intrarii text

        return linie;

    }

    public void printLine(String text) {

        outTextGrafic.append(text + "\n");

        vertical.setValue(vertical.getMaximum() - vertical.getVisibleAmount());

        validate(); repaint();

    }

 

    public void setConexiune(ConexiuneRetea conexiune) {

        this.conexiune = conexiune;

    }

 

    class AscultatorInText implements ActionListener {

        // Tratarea actionarii intrarii de text (introducerii unui "Enter")

        public void actionPerformed(ActionEvent ev) {

           sirCitit = nextLine();

           conexiune.printLine(nume + ": " + sirCitit);

           if (sirCitit.equals(new String("BYE"))) System.exit(0); //Conditie oprire

        }    

    }

}

 

Clasa utilitara ConexiuneRetea incapsuleaza tratarea conexiunilor TCP:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import java.net.*;
import java.io.*;
import java.util.Scanner;
 
public class ConexiuneRetea{
    Socket conexiune;                
    Scanner scannerTCP;
    PrintStream printerTCP; 
 
    public ConexiuneRetea(Socket conexiune) throws IOException {                              
        this.conexiune = conexiune;
        this.scannerTCP = new Scanner(conexiune.getInputStream()); 
        this.printerTCP = new PrintStream(conexiune.getOutputStream()); 
    } 
    public void printLine(String text) { 
        this.printerTCP.println(text); 
        this.printerTCP.flush();
    }

 }

 

Clasa ServerChatN2N reprezinta serverul TCP care poate trata mai multi clienti:

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

import java.net.*;
import java.io.*; 
import javax.swing.JOptionPane;  
 
public class ServerChatN2N extends Thread {    
    private static int numarClienti = 0;
    private static int portTCP;
    private static ServerSocket serverTCP;
    private static Socket socketTCP;
    public static final int NUMAR_MAXIM_CLIENTI = 10;
    private static ConexiuneRetea[] conexiuni;
    private int numarulConexiuniiCurente; // incepe cu 0
 
    public ServerChatN2N(int numarulConexiuniiCurente) throws IOException {
        this.numarulConexiuniiCurente = numarulConexiuniiCurente;
    }
    public static void main (String args[]) throws IOException {
        conexiuni = new ConexiuneRetea[NUMAR_MAXIM_CLIENTI];
     portTCP=Integer.parseInt(JOptionPane.showInputDialog("Introduceti port server"));
        serverTCP = new ServerSocket(portTCP); // Creare socket server
        while (true) {
            socketTCP = serverTCP.accept();  // Creare socket
            conexiuni[numarClienti] = new ConexiuneRetea(socketTCP); 
            ServerChatN2N server = new ServerChatN2N(numarClienti++);
            server.start();
        }
    }
    public void removeConnexion(int crt) {
        for (int i=crt; i<numarClienti-1; i++) {
            conexiuni[i] = conexiuni[i+1];
        }
        numarClienti--; 
    }
    public void run() {  // Fir executie receptie prin socket
        String mesaj;
        while(true) {
            if (this.conexiuni[numarulConexiuniiCurente].scannerTCP.hasNextLine()){
               mesaj = this.conexiuni[numarulConexiuniiCurente].scannerTCP.nextLine();
                for (int i=0; i<numarClienti; i++) {
                    conexiuni[i].printLine(mesaj);
                }       
                if (mesaj.equals("BYE")) {
                    removeConnexion(numarulConexiuniiCurente);
                }
            } 
            try {                sleep(1000);            } 
            catch (InterruptedException e) {}
        }
    }
}

 

Clasa ClientChatN2N reprezinta clientul TCP cu interfata grafica:

 

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

import java.net.*;
import java.io.*; 
import javax.swing.JOptionPane;  
 
public class ClientChatN2N extends Thread {    
    private ConexiuneRetea conexiune;
    private Socket socketTCP;
    private int portTCP;
    private InetAddress adresaIP;
    DialogUtilizator dialog;
    String numeClient;
 
    public ClientChatN2N() throws IOException {
     portTCP=Integer.parseInt(JOptionPane.showInputDialog("Introduceti port server"));
     adresaIP=InetAddress.getByName(
                      JOptionPane.showInputDialog("Introduceti IP server"));
        numeClient = JOptionPane.showInputDialog("Introduceti un nickname");
        
        dialog = new DialogUtilizator(numeClient);
 
        socketTCP = new Socket(adresaIP, portTCP); // Creare socket 
        conexiune = new ConexiuneRetea(socketTCP);
        dialog.printLine("\nPentru oprire introduceti \"BYE\" si <Enter>\n");
    }
 
    public static void main (String args[]) throws IOException {
        ClientChatN2N client = new ClientChatN2N();
        client.dialog.setConexiune(client.conexiune); 
        client.start();
    }
 
    public void run() {  // Fir executie receptie prin socket
        String mesaj;
        while(true) {
            if (this.conexiune.scannerTCP.hasNextLine()){
                mesaj = this.conexiune.scannerTCP.nextLine();
                this.dialog.printLine(mesaj);
                
                if (mesaj.equals("BYE")) break;     // Testarea conditiei de oprire 
            } 
            try {                sleep(1000);            } 
            catch (InterruptedException e) {}
        }
        try {
            this.socketTCP.close(); // Inchidere socket (implicit fluxuri)
        } catch (IOException ioe) {};
 
        this.dialog.printLine("Bye!"); 
        System.exit(0);
    }
}

 

 

 

                              

 

In laborator:

1. Lansati in executie BlueJ. Inchideti proiectele anterioare (Ctrl+W). Creati un proiect chatn2n

2. Creati cele 4 clase ale caror coduri sunt date mai sus. Compilati codurile.

 

Optional, in laborator:

1. La unul dintre calculatoare right-click pe clasa ServerChatN2N. Selectati si executati main(). Folositi numarul de port 4000. La alte 2-3 calculatoare (daca nu aveti la dispozitie un alt calculator in retea, deschideti mai multe sesiuni BlueJ) right-click pe clasa Client ChatN2N, selectati si executati main(). Folositi adresa primului calculator (pe care se executa ServerChatN2N) si numarul de port 4000.

 

6.4. Precizari privind mini-proiectul pentru examen        

 

Tema mini-proiectului este: Sistem de comunicatie (avansat, pentru bonus) client-server (N-la-N) bazat pe socket TCP, fire de executie si interfata grafica Swing pornind de la codurile sursa date ca exemplu la acest laborator (NU de la zero!).

 

Proiectul va contine (pentru fiecare grup de studenti):

- dosarul cu documentatia proiectului (6-8 pagini), incluzand:

      - titlul proiectului si autorii – cu indicarea rolului fiecaruia - prima pagina

            - descrierea claselor si metodelor utilizate (rol, structura, comportament) - 3 pagini

            - documentarea solutiilor tehnice care nu apar in exemple, a problemelor intampinate,

            - descrierea modului de utilizare al sistemului (cu screenshot-uri) – 2 pagini

- listingurile codurilor sursa atasate ca anexa la dosar

- proiectul in forma electronica (pe CD, atasat de dosar cu un plic), continand:

      - documentatia,

- codurile sursa ale proiectului si

      - codurile sursa ale temelor de casa date la lucrarile de laborator 1, 2, 3 si 4.

 

Sustinerea proiectului presupune:

- predarea dosarului cu documentatia proiectului (avand atasata forma electronica)

- prezentarea executiei sistemului daca acesta include facilitati noi, avansate (pentru bonus)

- prezentarea rolului fiecarui autor la realizarea sistemului si a documentarii lui

- prezentarea solutiilor tehnice noi (pentru bonus)

- raspunsuri la intrebari privind detalii ale proiectului (din documentatie si listinguri)

 

Imbunatatiri / modificari posibile (pentru bonus) de la simplu la complex:


- adaugarea unui buton BYE

- interfata grafica si la server (ca la client)

- imbunatatiri ale tratarii exceptiilor

- canal privat intre 2 clienti prin analiza lexicala

- canal privat intre 2 clienti prin socket-uri noi

- lista utilizatori prosibili, la server, si autentificare cu nume si parola

- interfata grafica de monitorizare la server

- inlocuirea tabloului conexiunilor cu Vector

- logfile la clienti si / server pt. memorare dialog

- atasarea unor nickname-uri utilizatorilor

- difuzarea nickname-uri utilizatorilor si afisarea unei liste participantilor

- invitarea / anuntarea potentialilor utilizatori

- inlocuirea socketurilor TCP cu socketuri UDP

- trecerea de la client-server la un sistem descentralizat