Visualizzazione dei risultati da 1 a 8 su 8

Discussione: Problema applet :(

  1. #1

    Problema applet :(

    Salve. Ho un problema... allora, l'applet viene caricata correttamente, ma quando vado a cliccare sul JButton per avviare una classe che estende JFrame, mi si blocca tutto e non riesco più a chiudere... perchè fa così?

    server.html
    codice:
    <html>
    	<applet code = "ServerApplet.class" width = "120" height = "50"></applet>
    </html>
    Server.java
    codice:
    import java.io.EOFException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class Server extends JFrame
    {
    	private JTextField enterField;
    	private JTextArea displayArea;
    	private ObjectOutputStream output;
    	private ObjectInputStream input;
    	private ServerSocket server;
    	private Socket connection;
    	private int counter = 1;
    	
    	public Server()
    	{
    		super ("Server");
    		setSize (300, 150);
    		setLocationRelativeTo (null);
    		setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
    		
    		enterField = new JTextField();
    		enterField.setEditable (false);
    		enterField.addActionListener
    		(
    			new ActionListener()
    			{
    				public void actionPerformed (ActionEvent event)
    				{
    					sendData (event.getActionCommand());
    					enterField.setText ("");
    				}
    			}
    		);
    		
    		add (enterField, BorderLayout.NORTH);
    		
    		displayArea = new JTextArea();
    		add (new JScrollPane (displayArea), BorderLayout.CENTER);
    		
    		setVisible (true);
    	}
    	
    	public void runServer()
    	{
    		try
    		{
    			server = new ServerSocket (12345, 100);
    			
    			while (true)
    			{
    				try
    				{
    					waitForConnection();
    					getStreams();
    					processConnection();
    				}
    				catch (EOFException exception)
    				{
    					displayMessage ("\nServer terminated connection");
    				}
    				finally
    				{
    					closeConnection();
    					counter++;
    				}
    			}
    		}
    		catch (IOException exception)
    		{
    			exception.printStackTrace();
    		}
    	}
    	
    	private void waitForConnection() throws IOException
    	{
    		displayMessage ("Waiting for connection\n");
    		connection = server.accept();
    		
    		displayMessage ("Connection " + counter + " received from: " + connection.getInetAddress().getHostName());
    	}
    	
    	private void getStreams() throws IOException
    	{
    		output = new ObjectOutputStream (connection.getOutputStream());
    		output.flush();
    		
    		input = new ObjectInputStream (connection.getInputStream());
    		
    		displayMessage ("\nGot I/O streams\n");
    	}
    	
    	private void processConnection() throws IOException
    	{
    		String message = "Connection successful";
    		sendData (message);
    		
    		setTextFieldEditable (true);
    		
    		do
    		{
    			try
    			{
    				message = (String) input.readObject();
    				displayMessage ("\n" + message);
    			}
    			catch (ClassNotFoundException exception)
    			{
    				displayMessage ("\nUnknown object type received");
    			}
    		} while (!message.equals ("CLIENT>>> TERMINATE"));
    	}
    	
    	private void closeConnection()
    	{
    		displayMessage ("\nTerminating connection\n");
    		setTextFieldEditable (false);
    		
    		try
    		{
    			output.close();
    			input.close();
    			connection.close();
    		}
    		catch (IOException exception)
    		{
    			exception.printStackTrace();
    		}
    	}
    	
    	private void sendData (String message)
    	{
    		try
    		{
    			output.writeObject ("SERVER>>> " + message);
    			output.flush();
    			displayMessage ("\nSERVER>>> " + message);
    		}
    		catch (IOException exception)
    		{
    			displayArea.append ("\nError writing object");
    		}
    	}
    	
    	private void displayMessage (final String messageToDisplay)
    	{
    		SwingUtilities.invokeLater
    		(
    			new Runnable()
    			{
    				public void run()
    				{
    					displayArea.append (messageToDisplay);
    				}
    			}
    		);
    	}
    	
    	private void setTextFieldEditable (final boolean editable)
    	{
    		SwingUtilities.invokeLater
    		(
    			new Runnable()
    			{
    				public void run()
    				{
    					enterField.setEditable (editable);
    				}
    			}
    		);
    	}
    }
    ServerApplet.java
    codice:
    import javax.swing.JApplet;
    import javax.swing.JButton;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class ServerApplet extends JApplet
    {
    	private JButton button;
    	
    	public void init()
    	{
    		button = new JButton ("Start Server");
    		button.addActionListener
    		(
    			new ActionListener()
    			{
    				public void actionPerformed (ActionEvent event)
    				{
    					Server server = new Server();
    					server.runServer();
    				}
    			}
    		);
    		
    		add (button);
    	}
    }

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Problema applet :(

    Originariamente inviato da Dreamer89
    mi si blocca tutto e non riesco più a chiudere... perchè fa così?
    Per le solite questioni dei thread e del EDT (mi sa che dovresti approfondirle un pochino).

    Quando viene invocato il actionPerformed(), si è nel contesto del EDT. Ma il metodo che invochi (runServer() ) è "bloccante" ovvero sta lì ad aspettare connessioni. Vuol dire che stai tenendo impegnato tu il EDT e non va affatto bene. Devi cercare sempre di impegnare il EDT il meno possibile. Se non ritorni dall'evento, il framework non ha possibilità di dispacciare altri eventi, di disegnare/aggiornare la interfaccia utente ecc.... Cioè la tua interfaccia grafica è "congelata".

    E sempre parlando dei thread, quando il metodo init() della applet viene invocato, non si è nel contesto del EDT. Quindi anche qui dovresti usare invokeLater per eseguire la inizializzazione della tua interfaccia nel contesto del EDT.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Allora, ho provato a modificare ServerApplet.java in questo modo:
    codice:
    import javax.swing.JApplet;
    import javax.swing.JButton;
    import javax.swing.SwingUtilities;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class ServerApplet extends JApplet
    {
    	private JButton button;
    	
    	public void init()
    	{
    		button = new JButton ("Start Server");
    		button.addActionListener
    		(
    			new ActionListener()
    			{
    				public void actionPerformed (ActionEvent event)
    				{
    					startServer();
    				}
    			}
    		);
    		
    		add (button);
    	}
    	
    	private void startServer()
    	{
    		SwingUtilities.invokeLater
    		(
    			new Runnable()
    			{
    				public void run()
    				{
    					Server server = new Server();
    					server.runServer();					
    				}
    			}
    		);
    	}
    }
    Il problema c'è ancora, quindi devo modificare qualche altra cosa, ma non ho idea di come fare per non tener impegnato il thead... crearne un altro?

  4. #4
    Ah, un'altra cosa, se eseguo Server senza utilizzare applet, cioè come un'applicazione normale, il programma non si blocca e viene eseguito correttamente. Cos'è quindi che non va se uso un'applet?

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Dreamer89
    Il problema c'è ancora
    Certo ... hai solo spostato più avanti nel tempo il problema. startServer() è velocissimo ... deposita solo nella coda dei task "da fare" il tuo Runnable. Il metodo actionPerformed termina subito, Swing fa quel che deve fare e ad un certo punto si accorge che c'è un Runnable da eseguire e lo esegue. Ma lì siamo al punto di prima.

    Originariamente inviato da Dreamer89
    ma non ho idea di come fare per non tener impegnato il thead... crearne un altro?
    Bingo! Sì, devi eseguire il server e il suo loop in un thread a sé stante.

    Originariamente inviato da Dreamer89
    Ah, un'altra cosa, se eseguo Server senza utilizzare applet, cioè come un'applicazione normale, il programma non si blocca
    Bisogna vedere cosa hai scritto per la applicazione .... ma se a seguito di un evento, nel actionPerformed fai la stessa identica cosa, si blocca certamente!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Allora, ho provato a fare così:

    codice:
    import javax.swing.JApplet;
    import javax.swing.JButton;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ExecutorService;
    
    public class ServerApplet extends JApplet
    {
    	private JButton button;
    	private ExecutorService executor;
    	
    	public void init()
    	{
    		executor = Executors.newFixedThreadPool (1);
    		
    		button = new JButton ("Start Server");
    		button.addActionListener
    		(
    			new ActionListener()
    			{
    				public void actionPerformed (ActionEvent event)
    				{
    					executor.execute
    					(
    						new Runnable()
    						{
    							public void run()
    							{
    								Server server = new Server();
    								server.runServer();
    							}
    						}
    					);
    					executor.shutdown();
    				}
    			}
    		);
    		
    		add (button);
    	}
    }
    Il frame si apre correttamente e funziona bene, però nello stesso tempo in cui lo apro, vengono lanciate una marea di eccezioni che la finestra del dos non riesce a contenere XD Poi se chiudo il frame e tento di riaprirlo, vengono lanciate altre eccezioni e la nuova finestra non viene più aperta!

  7. #7
    Ho modificato così:
    codice:
    import javax.swing.JApplet;
    import javax.swing.JButton;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class ServerApplet extends JApplet
    {
    	private JButton button;
    	
    	public void init()
    	{
    		button = new JButton ("Start Server");
    		button.addActionListener
    		(
    			new ActionListener()
    			{
    				public void actionPerformed (ActionEvent event)
    				{
    					Thread serverThread = new Thread
    					(
    						new Runnable()
    						{
    							public void run()
    							{
    								Server server = new Server();
    								server.runServer();
    							}
    						}
    					);
    					serverThread.start();
    				}
    			}
    		);
    		
    		add (button);
    	}
    }
    Non mi da i problemi di prima, però se chiudo il frame, e lo riapro cliccando di nuovo sul pulsante dell'applet, viene lanciata una BindException, come se la connessione del Socket fosse ancora attiva, e quindi come se il frame precedente si fosse solo nascosto e non chiuso. Forse quel DISPOSE_ON_CLOSE del frame di Server non va bene? Come faccio a chiuderlo bene?

  8. #8
    Ho risolto facendo in modo che quando chiudo il frame il Socket e il ServerSocket vengano chiusi col metodo close() Anche se non capisco perchè non lo faccia automaticamente il dispose().

    codice:
    import java.io.EOFException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.SocketException;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowListener;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class Server extends JFrame
    {
    	private JTextField enterField;
    	private JTextArea displayArea;
    	private ObjectOutputStream output;
    	private ObjectInputStream input;
    	private ServerSocket server;
    	private Socket connection;
    	private int counter = 1;
    	private boolean closingFlag = false;
    	
    	public Server()
    	{
    		super ("Server");
    		setSize (300, 150);
    		setLocationRelativeTo (null);
    		setDefaultCloseOperation (JFrame.DO_NOTHING_ON_CLOSE);
    		
    		enterField = new JTextField();
    		enterField.setEditable (false);
    		enterField.addActionListener
    		(
    			new ActionListener()
    			{
    				public void actionPerformed (ActionEvent event)
    				{
    					sendData (event.getActionCommand());
    					enterField.setText ("");
    				}
    			}
    		);
    		
    		add (enterField, BorderLayout.NORTH);
    		
    		displayArea = new JTextArea();
    		add (new JScrollPane (displayArea), BorderLayout.CENTER);
    		
    		addWindowListener
    		(
    			new WindowAdapter()
    			{
    				public void windowClosing (WindowEvent event)
    				{
    					closingFlag = true;
    					closeConnection();
    					dispose();
    				}
    			}
    		);
    		
    		setVisible (true);
    	}
    	
    	public void runServer()
    	{
    		try
    		{
    			server = new ServerSocket (12345, 100);
    			
    			while (true)
    			{
    				try
    				{
    					waitForConnection();
    					getStreams();
    					processConnection();
    				}
    				catch (EOFException exception)
    				{
    					displayMessage ("\nServer terminated connection");
    				}
    				finally
    				{
    					closeConnection();
    					counter++;
    				}
    			}
    		}
    		catch (SocketException exception){}
    		catch (IOException exception)
    		{
    			exception.printStackTrace();
    		}
    	}
    	
    	private void waitForConnection() throws IOException
    	{
    		displayMessage ("Waiting for connection\n");
    		connection = server.accept();
    		
    		displayMessage ("Connection " + counter + " received from: " + connection.getInetAddress().getHostName());
    	}
    	
    	private void getStreams() throws IOException
    	{
    		output = new ObjectOutputStream (connection.getOutputStream());
    		output.flush();
    		
    		input = new ObjectInputStream (connection.getInputStream());
    		
    		displayMessage ("\nGot I/O streams\n");
    	}
    	
    	private void processConnection() throws IOException
    	{
    		String message = "Connection successful";
    		sendData (message);
    		
    		setTextFieldEditable (true);
    		
    		do
    		{
    			try
    			{
    				message = (String) input.readObject();
    				displayMessage ("\n" + message);
    			}
    			catch (ClassNotFoundException exception)
    			{
    				displayMessage ("\nUnknown object type received");
    			}
    		} while (!message.equals ("CLIENT>>> TERMINATE"));
    	}
    	
    	private void closeConnection()
    	{
    		displayMessage ("\nTerminating connection\n");
    		setTextFieldEditable (false);
    		
    		try
    		{
    			if (output != null)
    				output.close();
    			if (input != null)
    				input.close();
    			if (connection != null)
    				connection.close();
    			if (server != null && closingFlag)
    				server.close();
    		}
    		catch (IOException exception)
    		{
    			exception.printStackTrace();
    		}
    	}
    	
    	private void sendData (String message)
    	{
    		try
    		{
    			output.writeObject ("SERVER>>> " + message);
    			output.flush();
    			displayMessage ("\nSERVER>>> " + message);
    		}
    		catch (IOException exception)
    		{
    			displayArea.append ("\nError writing object");
    		}
    	}
    	
    	private void displayMessage (final String messageToDisplay)
    	{
    		SwingUtilities.invokeLater
    		(
    			new Runnable()
    			{
    				public void run()
    				{
    					displayArea.append (messageToDisplay);
    				}
    			}
    		);
    	}
    	
    	private void setTextFieldEditable (final boolean editable)
    	{
    		SwingUtilities.invokeLater
    		(
    			new Runnable()
    			{
    				public void run()
    				{
    					enterField.setEditable (editable);
    				}
    			}
    		);
    	}
    }

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.