[Java] Multithreaded GUI loopt vast *

Pagina: 1
Acties:

  • joostdiepenmaat
  • Registratie: Maart 2001
  • Laatst online: 05-09-2022
De situatie is als volgd: Er is een progje dat via een public key system sleutels uitwisseld met een andere gebruiker (connect naar socket). De gebruiker draait hetzelfe progje(progje heeft serversocket). Vervolgens dient er encrypted data verzonden te kunnen worden.

Het probleem: wanneer ik over het netwerk connect naar een andere pc dan slaat aan 1 kant de GUI op hol(grijs). De andere kant werkt gewoon. Ik heb het eea met betrekking tot Runnable geimplementeerd, maar dit lost mijn probleem niet op.

De SecureClientHandler heeft een GUI waarin boodschappen ontvangen kunnen worden. Vanuit de GUI kunnen berichten naar de SecureClientHandler(Thread) verzonden worden die ze naar de andere gebruiker stuurt.

De verificatie van de twee clients naar elkaar toe levert geen problemen op(handshake), echter wanneer ik de loop start waarin ingekomen text gelezen wordt slaat 1 van de twee GUI's op hol (Niet beide terwijl het wel hetzelfde programma is :S)

Kan iemand mij vertellen waar mijn probleem zit?

code
Java:
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
package gui;
import java.awt.event.*;
import javax.swing.*;
import systemMain.*;
import java.net.*;
import secureConnection.*;

public class MainGui extends JFrame implements ActionListener{
    
    /* sendArea, area to type your message */
    private JTextField addressField;
    
    /* sendButton, to send your message */
    private JButton connectButton;
    
    /* displays connections status */
    private JTextArea statusArea;
    
    private SystemMain systemMain;

    public MainGui(SystemMain systemMain){
        this.systemMain = systemMain;
        
        setTitle("31CRY, opdracht 1, Public Key System");
        setSize(300,300);
        setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        /* sendPanel, with sendArea and sendButton */
        JPanel connectPanel = new JPanel();
        
        /* Center, receivearea */
        statusArea = new JTextArea();
        statusArea.setLineWrap(true);
        statusArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(statusArea);
        getContentPane().add(scrollPane, "Center");


        /* sendButton in sendPanel */
        connectButton = new JButton("Connect");
        connectButton.addActionListener(this);
        connectPanel.add(connectButton, "East");
        
        /* sendArea in sendPanel */
        addressField = new JTextField("127.0.0.1");
        addressField.setColumns(15);
        
        connectPanel.add(addressField, "West");
        getContentPane().add(connectPanel, "North");

    }
    
    public void actionPerformed(ActionEvent evt){
        Object source = evt.getSource();
        if(source == connectButton){
            String ip = addressField.getText();
            appendStatusMessage("Trying to connect to: " + ip);
            try {
                Socket other = new Socket(ip, 80);
                SecureClientHandler secureClientHandler = new SecureClientHandler(other, systemMain);
                secureClientHandler.start();
                secureClientHandler.startRunning();
            } catch (Exception e){
                appendStatusMessage("Failed to create socket to: " + ip);
            }
        }
    }

    public void appendStatusMessage(String message){
        statusArea.append(message + "\n");
    }
}

Java:
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package secureConnection;

import java.net.*;
import systemMain.*;
import keyManagement.*;
import gui.*;
import java.io.*;
import java.math.BigInteger;
import java.util.*;
import java.awt.event.*;
public class SecureClientHandler extends Thread{
    
    private Cryption cryption;
    private Socket socketOther;
    private SystemMain systemMain;
    private ChatSessionGui chatSessionGui;
    private BufferedReader in;
    private PrintWriter out;
    private KeyManager keyManager;
    private BigInteger publicKey;
    private boolean chatRunning = false;
    
    public SecureClientHandler(Socket socketOther, SystemMain systemMain){
        this.socketOther = socketOther;
        this.systemMain = systemMain;
        keyManager = systemMain.getKeyManager();
        publicKey = keyManager.getPublicKey(); 
        chatSessionGui = new ChatSessionGui(this);
        chatSessionGui.addWindowListener(
            new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                stopSession();
                }
            }
        );

    }
    
    public void startRunning(){
        try{
            in = new BufferedReader(new InputStreamReader(socketOther.getInputStream()));
            out = new PrintWriter(socketOther.getOutputStream(), true);
            if(handShake()){
                out.flush();
                cryption = new Cryption(keyManager.getConventionalKey(socketOther.getInetAddress()).intValue());
                chatSessionGui.show();
                boolean chatRunning = true;
                /** HIER GAAT HET VERKEERD, GUI GAAT HANGEN (als ik while(chatRunning weghaal gaat 't ok **/
                while(chatRunning){
                String encryptedLine = in.readLine();
                    if(!encryptedLine.trim().equals("QUIT")){
                        StringTokenizer words = new StringTokenizer(encryptedLine, " \t\n\r");
                        String line = "";
                        while(words.hasMoreTokens()){
                            line += this.decrypt(words.nextToken()) + " ";
                        }
                        chatSessionGui.appendIncomingMessage(line);
                        System.out.println(line);
                    } else {
                        chatRunning = false;
                        stopSession();
                    }
                }
                /** EINDE PROBLEEM **/
            } else {
                systemMain.getMainGui().appendStatusMessage(getRemoteAddress() + ": FAILED to authenticate.");
            }
        } catch(Exception e){
            systemMain.getMainGui().appendStatusMessage(e.toString());
        }
    }

    public void stopSession(){
        chatSessionGui.dispose();
        out.println("QUIT");
        keyManager.closeSession(socketOther.getInetAddress());
        try{
            socketOther.close();
        } catch(Exception e){
            System.out.println(e);
        }
    }

    public boolean handShake(){
        boolean shaked = false;
        try{
            
            boolean AUTHdone = false;
            while(!AUTHdone){
                out.println("AUTH");
                String auth = in.readLine();
                if(auth.trim().equals("AUTH")){
                    AUTHdone = true;
                }
            }
            //System.out.println("auth done");
            boolean PUBKEYdone = false;
            while(!PUBKEYdone){
                out.println(publicKey.toString());
                String key = in.readLine();
                if(!key.trim().equals("AUTH")){
                    BigInteger publicKeyOther = new BigInteger(key.trim());
                    keyManager.startSession(socketOther.getInetAddress(),publicKeyOther);
                    PUBKEYdone = true;
                }
            }
            //System.out.println("pubkey done");
            
            boolean AUTHOKdone = false;
            while(!AUTHOKdone){
                out.println("AUTHOK");
                String auth = in.readLine();
                if(auth.trim().equals("AUTHOK")){
                    AUTHOKdone = true;
                }
            }
            //System.out.println("authok done");
            
            shaked = true;
        } catch(Exception e){
            systemMain.getMainGui().appendStatusMessage(e.toString());
        }
        return shaked;
    }
    
    public String encrypt(String word){
        return cryption.encode(word);
    }
    
    public String decrypt(String word){
        return cryption.decode(word);
    }

    public String getRemoteAddress(){
        return socketOther.getRemoteSocketAddress().toString();
    }   
    
    public void sendMessage(String line){
        StringTokenizer words = new StringTokenizer(line, " \t\n\r");
        String encryptedLine = "";
        while(words.hasMoreTokens()){
            encryptedLine += this.encrypt(words.nextToken()) + " ";
        }
        out.println(encryptedLine);
    } 
}

als ik gewoon met telnet naar mijn progje connect geeft het geen enkel probleem.

[ Voor 15% gewijzigd door joostdiepenmaat op 17-10-2003 12:33 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik snap niet waarom jij die SwingUtilities.invokeLater gebruikt bij send message. Die methode wordt aangeroepen bij de action performed methode en deze draait dus al op de event dispatching thread. Je hoeft dan niet nog een keer op de event dispatching thread te komen om daarna het bericht door te geven aan jouw hoofd thread.

Verder zie ik je ook nergens Thread.start aanroepen. Dus jouw 'Thread' object wordt gewoon beschouwt als een normaal object en de methode aanroepen vinden dus ook plaats op de event dispatching thread.

Daarom slaat de gui ook op hol. De event dispatching thread is druk bezig om te decoden, en heeft geen tijd meer om repaint requests ed uit te voeren. Het lijkt dan alsof je applicatie is bevroren.

[ Voor 49% gewijzigd door Alarmnummer op 17-10-2003 13:12 ]


  • joostdiepenmaat
  • Registratie: Maart 2001
  • Laatst online: 05-09-2022
Alarmnummer schreef op 17 October 2003 @ 12:01:
Ik snap niet waarom jij die SwingUtilities.invokeLater gebruikt bij send message. Die methode wordt aangeroepen bij de action performed methode en deze draait dus al op de event dispatching thread. Je hoeft dan niet nog een keer op de event dispatching thread te komen om daarna het bericht door te geven aan jouw hoofd thread.

Verder zie ik je ook nergens Thread.start aanroepen. Dus jouw 'Thread' object wordt gewoon beschouwt als een normaal object en de methode aanroepen vinden dus ook plaats op de event dispatching thread.

Daarom slaat de gui ook op hol. De event dispatching thread is druk bezig om te decoden, en heeft geen tijd meer om repaint requests ed uit te voeren. Het lijkt dan alsof je applicatie is bevroren.
Die invokelater heb ik gekilled, 't is me nog wat onduidelijk hoe die precies toegpast dient te worden. Thread.start gebeurt vanuit de mainGui of SecureServerSocket(classes die secureClientHandlers aan kunnen maken). Na de aanpassingen zit ik alleen nog met hetzelfde probleem:S

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

deepman schreef op 17 oktober 2003 @ 12:36:
[...]

Die invokelater heb ik gekilled, 't is me nog wat onduidelijk hoe die precies toegpast dient te worden.
Stel dat jouw thread loopt te runnen en je wilt weer terug komen naar de gui thread om daarvandaan iets in de gui te doen (heb je verder geen gezeik met concurrency control). Dan kun je een runnable in de invokeAndWait (dan gaat jouw thread slapen totdat dat bericht verstuurd is) of de invokeLater( dan heeft jouw thread een commando gepost die later geexecute gaat worden op de event dispatching thread maar jouw thread die gaat gewoon verder)
Thread.start gebeurt vanuit de mainGui of SecureServerSocket(classes die secureClientHandlers aan kunnen maken). Na de aanpassingen zit ik alleen nog met hetzelfde probleem:S
Als je en thread wilt starten doe je het volgende:

Java:
1
2
Thread t = new BlaBlaThread();
t.start()


Jij mag zelf de start methode niet overriden, je moet namelijk de run methode overriden. Beter kan je een Runnable maken en die in een thread plaatsen:


Java:
1
2
3
4
5
6
7
8
9
class BlaatRunnable implements Runnable{
     public void run(){
         //zware klus komt hier
     }
}


Thead t = new Thread(new BlaatRunnable());
t.start();

[ Voor 3% gewijzigd door Alarmnummer op 17-10-2003 12:41 ]


  • joostdiepenmaat
  • Registratie: Maart 2001
  • Laatst online: 05-09-2022
Onwijs bedankt, het werkt nu!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Als je vanuit jouw thread contact wilt opnemen met andere objecten (dus methodes aanroepen/bij fields komen) pas dan verdomde goed op dat je geen raceproblemen ed krijgt. Als je iets wilt aanroepen vanuit jouw thread naar de gui toe, dan zou je daar die invokeLater ed voor kunnen gebruiken:


Java:
1
2
3
4
5
6
7
8
9
10
11
12
class DikkeRunnable implements Runnable{
    public void run(){
        //zwaar werk
        SwingUtilities.invokeAndWait(new ReadyRunnable());
    }
}

class ReadyRunnable implements Runnable{
    public void run(){
       _hoodscherm.threadIsKlaar();
   }
}


Op deze manier is er tenminste altijd maar 1 thread actief op jouw gui: de event dispatching thread.


[edit]
Concurrent Programming in Java(TM): Design Principles and Pattern (2nd Edition) van Doug Lea is een dikke aanrader.

[ Voor 18% gewijzigd door Alarmnummer op 17-10-2003 13:13 ]

Pagina: 1