Aplikacja klient - serwer. Użycie klasy Socket.

0

Cześć,
piszę program, w którym w jednym okienku jest generowana i wyświetlana tablica wartości całkowitych, zaś w drugim podawane współrzędne x, y tej tablicy i pobierana wartość z pierwszej aplikacji oraz rysowany wykres słupkowy z podaną wartością. Z częścią graficzną już się uporałem. Przyszedł czas na zapewnienie łączności między aplikacjami i tutaj pojawił się problem, bo nie wiem czy dobrze się do tego zabrałem.
Oto mój kod:
Serwer:

package lab05_pop;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.Random;

import javax.swing.*;

@SuppressWarnings("serial")
public class Serwer extends JFrame implements ActionListener {
    JButton generuj;
    JTextArea poleTekstowe;
    int [][] tablica = new int [10][10];
    ServerSocket polaczenie = null;
    Socket gniazdo = null;
    OutputStream wyX;
    OutputStream wyY;
    DataOutputStream zapisX = null;
    DataOutputStream zapisY = null;
    InputStream weX;
    InputStream weY;
    BufferedReader odczytX = null;
    BufferedReader odczytY = null;
    String x ="", y = "";
    String wartosc = "";
    DataOutputStream komorkaTablicy = null;
    
    void wypełnij (){
        Random gen = new Random();
        for (int i=0; i<tablica.length; i++){
            for (int j=0; j<tablica[i].length; j++)
                tablica[i][j]=gen.nextInt(10);
        }
    }
    
    void wyświetl (){
        for (int i=0; i<tablica.length; i++){
            for (int j=0; j<tablica[i].length; j++){
                poleTekstowe.append(" " + tablica[i][j]);
            }
            poleTekstowe.append("\n");
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        poleTekstowe.setText("");
        wypełnij();
        wyświetl();
    }
    
    public void łączność (){
    try {
        polaczenie = new ServerSocket(8864);
        }
        catch(IOException e)
        { System.out.println("Nie można utworzyć gniazda serwera.");   }

    try {
        gniazdo = polaczenie.accept();
        }
        catch(IOException e)
        {   System.out.println("Nie można nawiązać połączenia z klientem.");   }
                              
    try {
        weX=gniazdo.getInputStream();
        }
        catch(IOException e)
        {   System.out.println("Nie można pobrać strumienia wejściowego.");   }

    try {
        wyX=gniazdo.getOutputStream();
        }
        catch(IOException e)
        {   System.out.println("Nie można pobrać strumienia wyjściowego.");   }
    try {
        weY=gniazdo.getInputStream();
        }
        catch(IOException e)
        {   System.out.println("Nie można pobrać strumienia wejściowego.");   }

    try {
        wyY=gniazdo.getOutputStream();
        }
        catch(IOException e)
        {   System.out.println("Nie można pobrać strumienia wyjściowego.");   }

    while(true){
    try{
        odczytX = new BufferedReader(new InputStreamReader(weX));
        odczytY = new BufferedReader(new InputStreamReader(weY));
        
        x = odczytX.readLine();
        y = odczytY.readLine();
                        
        if(x == null && y == null)
         {
            gniazdo.close();
            System.exit(0);
         }
                        
         else if(x != null && y != null)
              {
                     for (int i=0; i<tablica.length; i++){
                         for (int j=0; j<tablica[i].length; j++){
                         if (x==String.valueOf(i) && y==String.valueOf(j))
                             wartosc = String.valueOf(tablica[i][j]);
                         }
                     }
              }
                                    
       } catch(IOException e){  System.out.println("Problem wejścia - wyjścia.");  }
    }   
}
    

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Serwer serwer = new Serwer();
                    serwer.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Serwer (){
        setTitle ("Serwer");
        setSize(400, 500);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);
        
        generuj = new JButton ("Generuj");
        generuj.setBounds(150, 400, 100, 20);
        add(generuj);
        generuj.addActionListener (this);
        
        poleTekstowe = new JTextArea ();
        poleTekstowe.setBounds(75, 20, 250, 300);
        add(poleTekstowe);
        Font font = new Font("Verdana", Font.BOLD, 23);
        poleTekstowe.setFont(font);
        poleTekstowe.setLineWrap(true);
    }
}

Klient:

package lab05_pop;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class Klient extends JFrame implements ActionListener  {
    JTextArea poleX, poleY;
    JButton pobierz;
    Socket polaczenie = null;
    OutputStream wyX;
    OutputStream wyY;
    InputStream weX;
    InputStream weY;
    BufferedReader odczytX = null;
    BufferedReader odczytY = null;
    Wczytanie wczytanie = null;
    
    
    public void linie (Graphics g){
        g.drawLine(50, 240, 50, 40);    //oś y = 200 px
        g.drawLine(50, 240, 350, 240);    //oś x = 300 px
        g.drawLine(50, 40, 40, 50);
        g.drawLine(50, 40, 60, 50);
        g.drawLine(350, 240, 340, 230);
        g.drawLine(350, 240, 340, 250);
        for(int i=0; i<14; i++)
            g.drawLine(70+(i*20), 235, 70+(i*20), 245);
        for(int i=0; i<9; i++)
            g.drawLine(45, 220-(i*20), 55, 220-(i*20));
        g.drawString("0", 45, 255);
    }

    public void wykres (Graphics g){
        int wysokosc = 9;
        g.drawRect(70-10, 240, 20, -20*wysokosc);
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        linie (g2d);
        wykres (g2d);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        wczytanie=new Wczytanie(polaczenie, wyX, wyY);
        wczytanie.start();
    }
    
    class Wczytanie extends Thread {
        Socket polaczenie;
        OutputStream wyX;
        OutputStream wyY;
        DataOutputStream zapisX = null;
        DataOutputStream zapisY = null;
        InputStream weX;
        InputStream weY;
        BufferedReader odczytX = null;
        BufferedReader odczytY = null;
    
    public Wczytanie (Socket polaczenie, OutputStream wyX, OutputStream wyY)
    {
       this.polaczenie=polaczenie;
       this.wyX=wyX;
       this.wyY=wyY;
    }

    public void run() {
            try{
                wyX=polaczenie.getOutputStream();
                String x = poleX.getText();
                wyY=polaczenie.getOutputStream();
                String y = poleY.getText();
                
                if(x!=null && y!=null){
                    zapisX = new DataOutputStream(wyX);
                    zapisY = new DataOutputStream(wyY);
                }
                    
                weX=polaczenie.getInputStream();
                odczytX= new BufferedReader (new InputStreamReader(weX));
                weY=polaczenie.getInputStream();
                odczytY= new BufferedReader (new InputStreamReader(weY));
                                
            }
            catch(Exception e){ 
            }
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Klient klient = new Klient();
                    klient.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Klient (){
        setTitle ("Klient");
        setSize(400, 500);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);
        
        poleX = new JTextArea ();
        poleX.setBounds(75, 350, 100, 20);
        add(poleX);
        
        poleY = new JTextArea ();
        poleY.setBounds(225, 350, 100, 20);
        add(poleY);
        
        pobierz = new JButton ("Pobierz");
        pobierz.setBounds(150, 400, 100, 20);
        add(pobierz);
        pobierz.addActionListener (this);
        
        try{
            polaczenie= new Socket("localhost", 8866);
            } catch(Exception e){  
                
            }
    }
}

Pytania:
Jak zrobić aby przy kompilacji wyświetlały się oba okienka programu?
Czy mógłby ktoś rzucić okiem czy dobrze to piszę? Doszedłem do takiego momentu, że nie do końca wiem co dalej robić ani jak przetestować działanie przesyłu danych.
Proszę o wszelkie wskazówki i porady.
Pozdrawiam.

0

Na pewno przy kompilacji mają Ci się wyświetlać jakieś okna? Może jednak dopiero po uruchomieniu programów. Korzystasz z IDE, czy kompilujesz z ręki?
Pusta obsługa błędów to głupota, a w programie który nie działa, to już idiotyzm.
Serwer pracuje na porcie 8864, a klient łączy się z portem 8866. W klasie Serwer nigdzie nie wywołujesz metody łączność.

0

Ok, dziękuję za odpowiedź. Czyli, że na początek darować sobie obsługę błędów? Z tą metodą łączność, to racja, na razie pisałem to "na sucho" bez testowania. Z tymi portami to też racja.
Zależy mi, żeby po uruchomieniu pojawiały się oba okienka, czyli wykonywały się obie metody main(). Słyszałem coś o łączeniu klas w jeden projekt, czy coś takiego, ale nie do końca wiem czy to rozwiąże mój problem. Piszę to w Eclipsie.

1

Nie rezygnuj z obsługi błędów.

        try{
            polaczenie= new Socket("localhost", 8866);
            } catch(Exception e){  
                 //tu musi coś być, absolutne minimum to System.out.println(e);
            }

Nie ma żadnego znaczenia czy klasy będa w jednym projekcie czy w dwóch. Po prostu uruchom dwa programy.

0

Gdzie w klasie Serwer powinna być wywołana metoda "łączność"?

1

To już Twój wybór, w konstruktorze, może drugi przycisk, który ją wywołuje. Niezależnie od wyboru powinna być w innym wątku, w przeciwnym czekanie na klienta (metoda accept) zablokuje Ci interakcję z użytkownikiem.

0

Ok, udało się wszystko zrobić, wszystko działa jak należy prócz rysowania wykresu. Wymyśliłem to tak, że z każdym kliknięciem na przycisk "Pobierz" zwiększać się będzie licznik i ten licznik będzie "przesuwał" słupek wykresu na kolejną pozycję. Napisałem też funkcję "wykres" aczkolwiek, nie wiem jak do niej przekazać "wysokość", którą to otrzymuję z aplikacji Serwer i jest ona odczytywana z tablicy. Dodam jeszcze, że cały mechanizm przesyłu danych działa jak należy zostało mi dodanie rysowania wykresu. Pomoże ktoś?
Oto moja funkcja Klient:

package lab05_pop;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class Klient extends JFrame implements ActionListener  {
    JTextArea poleX, poleY;
    JButton pobierz;
    JLabel wypisz;
    int klikniecia = 0;
    
    public void linie (Graphics g){
        g.drawLine(50, 240, 50, 40);    //oś y = 200 px
        g.drawLine(50, 240, 350, 240);    //oś x = 300 px
        g.drawLine(50, 40, 40, 50);
        g.drawLine(50, 40, 60, 50);
        g.drawLine(350, 240, 340, 230);
        g.drawLine(350, 240, 340, 250);
        for(int i=0; i<14; i++)
            g.drawLine(70+(i*20), 235, 70+(i*20), 245);
        for(int i=0; i<9; i++)
            g.drawLine(45, 220-(i*20), 55, 220-(i*20));
        g.drawString("0", 45, 255);
    }
    
    public void wykres (Graphics g, int wysokosc, int i){
        g.drawRect(60+(i*20), 240, 20, -20*wysokosc);
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        linie (g2d);
        wykres (g2d, client.wysokosc, klikniecia);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        klikniecia++;
        Client client = new Client();
        client.run(Integer.parseInt(poleX.getText()), Integer.parseInt(poleY.getText()));
    }
    
    public class Client extends Thread{
        Socket gniazdo;
        ObjectOutputStream out;
         ObjectInputStream in;
         int wysokosc;
         Graphics g;
        Client(){}
        void run(int x, int y)
        {
            try{
                gniazdo = new Socket("localhost", 2004);
                out = new ObjectOutputStream(gniazdo.getOutputStream());
                out.flush();
                in = new ObjectInputStream(gniazdo.getInputStream());
                    try{
                        wyślij(x);
                        wyślij(y);
                        System.out.print(wysokosc = (int)in.readObject());
                    }
                    catch(ClassNotFoundException classNot){
                        System.err.println("Otrzymane dane są w nieznanym formacie");
                    }
                
            }
            catch(UnknownHostException unknownHost){
                System.err.println("Łączysz się z nieznanym hostem!");
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
            finally{
                try{
                    in.close();
                    out.close();
                    gniazdo.close();
                }
                catch(IOException ioException){
                    ioException.printStackTrace();
                }
            }
        }
        void wyślij (int wy)
        {
            try{
                out.writeObject(wy);
                out.flush();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
}

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Klient klient = new Klient();
                    klient.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    public Klient (){
        setTitle ("Klient");
        setSize(400, 500);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);
        
        poleX = new JTextArea ();
        poleX.setBounds(75, 350, 100, 20);
        add(poleX);
        
        poleY = new JTextArea ();
        poleY.setBounds(225, 350, 100, 20);
        add(poleY);
        
        pobierz = new JButton ("Pobierz");
        pobierz.setBounds(150, 400, 100, 20);
        add(pobierz);
        pobierz.addActionListener (this);
        
        wypisz = new JLabel ("");
        wypisz.setBounds (150, 400, 100, 20);
        add(wypisz);
    }
}

Tutaj niestety wykres się nie rysuje.

0

Dlaczego zamieszczasz błędny kod? Jego się nie da skompilować:

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        linie (g2d);
        wykres (g2d, client.wysokosc, klikniecia); //tutaj zmienna client nie istnieje
    }
0

Przepraszam, dopisałem tamten fragment kodu na szybko i zapomniałem dopisać to:

@SuppressWarnings("serial")
public class Klient extends JFrame implements ActionListener  {
    JTextArea poleX, poleY;
    JButton pobierz;
    JLabel wypisz;
    Client client = new Client();
    int klikniecia = 0;
0
    public void actionPerformed(ActionEvent e) {
        klikniecia++;
        client.run(Integer.parseInt(poleX.getText()), Integer.parseInt(poleY.getText()));
        repaint(); //na pewno brakuje tego wiersza
    }
0

Odświeża się z każdym kliknięciem, ale nie rysuje wykresu.

0

Daj aktualny kod Klienta i Serwera.

0

Serwer:

package lab05_pop;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.Random;

import javax.swing.*;


@SuppressWarnings("serial")
public class Serwer extends JFrame implements ActionListener {
    JButton generuj;
    JTextArea poleTekstowe;
    int [][] tablica = new int [10][10];
    Server server = new Server();
    
    public class Server extends Thread{
        ServerSocket serverSocket;
        Socket gniazdo = null;
        ObjectOutputStream out;
        ObjectInputStream in;
        int x=-1, y=-1;
        Server(){}
        public void run()
        {
            while (true){
            try{
                serverSocket = new ServerSocket(2004, 10);
                gniazdo = serverSocket.accept();
                out = new ObjectOutputStream(gniazdo.getOutputStream());
                out.flush();
                in = new ObjectInputStream(gniazdo.getInputStream());
                
                    try{
                        x = (int) in.readObject();
                        y = (int) in.readObject();
                        
                        if(x != -1 && y != -1)
                          {
                                 for (int i=0; i<tablica.length; i++){
                                     for (int j=0; j<tablica[i].length; j++){
                                     if (x==(i) && y==(j))
                                         wyślij(tablica[i][j]);
                                     }
                                 }
                          }
                    }
                    catch(ClassNotFoundException classnot){
                        System.err.println("Otrzymane dane są w nieznanym formacie");
                    }
                
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
            finally{
                try{
                    in.close();
                    out.close();
                    serverSocket.close();
                }
                catch(IOException ioException){
                    ioException.printStackTrace();
                }
            }
            }
        }
        void wyślij (int wy)
        {
            try{
                out.writeObject(wy);
                out.flush();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
}
    
    void wypełnij (){
        Random gen = new Random();
        for (int i=0; i<tablica.length; i++){
            for (int j=0; j<tablica[i].length; j++)
                tablica[i][j]=gen.nextInt(10);
        }
    }
    
    void wyświetl (){
        for (int i=0; i<tablica.length; i++){
            for (int j=0; j<tablica[i].length; j++){
                poleTekstowe.append(" " + tablica[i][j]);
            }
            poleTekstowe.append("\n");
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        poleTekstowe.setText("");
        wypełnij();
        wyświetl();
    }

    

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Serwer serwer = new Serwer();
                    serwer.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public Serwer (){
        setTitle ("Serwer");
        setSize(400, 500);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);
        
        generuj = new JButton ("Generuj");
        generuj.setBounds(150, 400, 100, 20);
        add(generuj);
        generuj.addActionListener (this);
        
        poleTekstowe = new JTextArea ();
        poleTekstowe.setBounds(75, 20, 250, 300);
        add(poleTekstowe);
        Font font = new Font("Verdana", Font.BOLD, 23);
        poleTekstowe.setFont(font);
        poleTekstowe.setLineWrap(true);
        Thread t = new Thread (server);
        t.start();
    }
}

Klient:

package lab05_pop;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class Klient extends JFrame implements ActionListener  {
    JTextArea poleX, poleY;
    JButton pobierz;
    JLabel wypisz;
    Client client = new Client();
    int klikniecia = 0;
    
    public void linie (Graphics g){
        g.drawLine(50, 240, 50, 40);    //oś y = 200 px
        g.drawLine(50, 240, 350, 240);    //oś x = 300 px
        g.drawLine(50, 40, 40, 50);
        g.drawLine(50, 40, 60, 50);
        g.drawLine(350, 240, 340, 230);
        g.drawLine(350, 240, 340, 250);
        for(int i=0; i<14; i++)
            g.drawLine(70+(i*20), 235, 70+(i*20), 245);
        for(int i=0; i<9; i++)
            g.drawLine(45, 220-(i*20), 55, 220-(i*20));
        g.drawString("0", 45, 255);
    }
    
    public void wykres (Graphics g, int wysokosc, int i){
        g.drawRect(60+(i*20), 240, 20, -20*wysokosc);
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        linie (g2d);
        wykres (g2d, client.wysokosc, klikniecia);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        klikniecia++;
        Client client = new Client();
        client.run(Integer.parseInt(poleX.getText()), Integer.parseInt(poleY.getText()));
        repaint();
    }
    
    public class Client{
        Socket gniazdo;
        ObjectOutputStream out;
         ObjectInputStream in;
         int wysokosc;
        Client(){}
        void run(int x, int y)
        {
            try{
                gniazdo = new Socket("localhost", 2004);
                out = new ObjectOutputStream(gniazdo.getOutputStream());
                out.flush();
                in = new ObjectInputStream(gniazdo.getInputStream());
                    try{
                        wyślij(x);
                        wyślij(y);
                        System.out.print(wysokosc = (int)in.readObject());
                    }
                    catch(ClassNotFoundException classNot){
                        System.err.println("Otrzymane dane są w nieznanym formacie");
                    }
                
            }
            catch(UnknownHostException unknownHost){
                System.err.println("Łączysz się z nieznanym hostem!");
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
            finally{
                try{
                    in.close();
                    out.close();
                    gniazdo.close();
                }
                catch(IOException ioException){
                    ioException.printStackTrace();
                }
            }
        }
        void wyślij (int wy)
        {
            try{
                out.writeObject(wy);
                out.flush();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
}

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Klient klient = new Klient();
                    klient.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    public Klient (){
        setTitle ("Klient");
        setSize(400, 500);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);
        
        poleX = new JTextArea ();
        poleX.setBounds(75, 350, 100, 20);
        add(poleX);
        
        poleY = new JTextArea ();
        poleY.setBounds(225, 350, 100, 20);
        add(poleY);
        
        pobierz = new JButton ("Pobierz");
        pobierz.setBounds(150, 400, 100, 20);
        add(pobierz);
        pobierz.addActionListener (this);
        
        wypisz = new JLabel ("");
        wypisz.setBounds (150, 400, 100, 20);
        add(wypisz);
    }
}
1
  1. Napisałem Ci wcześniej kod metody actionPerformed, a Ty masz inny (błędny) kod.
  2. Poczytaj w dokumentacji klasy Graphics jakie są parametry metody drawRect, Ty rysujesz prostokąt o ujemnej wysokości. Takiego prostokąta nie widać.
0
  1. Dzięki za znalezienie błędu, jak zwykle coś przeoczyłem.
  2. Taki prostokąt się rysuje bez problemu i jest to łatwiejszy sposób, bo jakbym chciał to pisać z dodatnia wartością, to musiałbym wykonywać dodatkowe obliczenia w celu przesunięcia mojego prostokąta do wysokości osi X.

Czy da się tak zarobić, żeby rysowały się kolejne słupki wykresu, ale nie odświeżały się cały rysunek? Chodzi mi o to, że jak teraz się odświeża to rysuje słupki dla aktualnych danych, a te poprzednie "znikają". Jak rozwiązać taki problem? Dodać jakąś pętle w której będą pamiętane poprzednie współrzędne + aktualne? Czy może jest jakaś inna opcja?

1

Tak, musisz pamiętać wszystkie wartości, które chcesz wyswietlać (tablica, kolekcja) i użyć pętli do wyswietlenia.

0

Wszystko się udało i działa jak należy. Dziękuję bardzo za pomoc :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1