Problem z funkcją destroy() w Japplet

0

Witam!

Piszę projekt na pracę inżynierską, jest to chat internetowy w oparciu o gniazda sieciowe. Aplikacja kliencka jest appletem na stronie. Problem pojawia się gdy po połączeniu z serwerem zamknę okno przeglądarki, apllet zostaje usunięty z pamięci, ale ustanowione połączenie między serwerem a hostem klienta nie zostaje zakończone do czasu wyłączenia serwera.

podobną operację przeprowadzałem przy użyciu applet viewer. Połączyłem się z serwerem i kliknąłem w krzyżyk żeby zamknąć klienta. W tym momencie zawieszał się applet viewer do czasu aż wyłączyłem server

Główna "ramka" appletu - sterowanie okienkami

package GUI;

import Main.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class Ramka extends JApplet /* JFrame */ implements ActionListener
{
	private JMenuBar mb;
	public JMenuItem polacz;
	JDesktopPane desktop;
	Obsluga obsluga = new Obsluga(this);
	
	

	public void init() 
	{
		mainFrame();
		menu();
		super.init();
	}
	

	
	@Override
	public void stop() {
		// TODO Auto-generated method stub
		super.stop();	
		obsluga.zakoncz();
	}
//	public Ramka ()
//	{
//		
//		mainFrame();
//		menu();
//
//	}
	
	private void mainFrame()
	{
		
		
//		addWindowListener(new ExitListener());
		
		Container content = getContentPane();
		content.setBackground(Color.gray);
		
		desktop = new JDesktopPane();
		desktop.setBackground(Color.gray);
		content.add(desktop, BorderLayout.CENTER);
//		this.setTitle("Chatroom Klient");
		this.setSize(800, 600);
		this.setLocation(100,100);
		
//		this.setLocation(0,0);
//		this.setSize(Toolkit.getDefaultToolkit().getScreenSize());
		
		this.setVisible(true);
		
		menu();
		okienko("loguj");
	}
	
	public void okienko(String ramka)
	{
		if (ramka.equals("loguj"))
		{
			JInternalFrame frame = new Loguj(this, obsluga);	
			desktop.add(frame);
			frame.setBorder(BorderFactory.createMatteBorder(
	                1, 1, 4, 2, Color.black));
			frame.moveToFront();
		    frame.setVisible(true);
		}
		if (ramka.equals("chat"))
		{
			JInternalFrame frame = new Chat(obsluga);		
			desktop.add(frame);
			frame.setBorder(BorderFactory.createMatteBorder(
	                1, 1, 4, 2, Color.black));
			frame.moveToFront();
		    frame.setVisible(true);
		}
	}
	public void okienko(String ramka, String label)
	{
		if (ramka.equals("dialog"))
		{
			JInternalFrame frame = new Dialogbox(this, label);		
			desktop.add(frame);
			frame.moveToFront();
		    frame.setVisible(true);
		}
  
		
	}
	
	private void menu()
	{
		
		//Pasek menu
		mb = new JMenuBar();
		JMenu plik = new JMenu("Plik"); // dodanie do paska  menu plik
		mb.add(plik);
		
		JSeparator separator = new JSeparator(); 
		plik.add(separator);
		
		polacz = new JMenuItem("Połącz");
		polacz.setActionCommand("polacz");
		polacz.addActionListener(this);
		polacz.setEnabled(false);
		plik.add(polacz);
		
		JMenuItem zamknij = new JMenuItem("Zamknij");
		zamknij.setActionCommand("zamknij");
		zamknij.addActionListener(this);
		plik.add(zamknij);
		
		this.setJMenuBar(mb); 
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("polacz") ) 
    	{
			okienko("loguj");
    	}
		if (e.getActionCommand().equals("zamknij") ) 
    	{
			System.exit(0);
    	}
	
	}	
}

klasa sterująca działaniem klienta

package Main;


import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;

import java.util.Iterator;
import java.util.LinkedList;

import GUI.*;


public class Obsluga {

	
	
	Socket gniazdo;
	
	public String imie;
	String wiadomosc;
	Nasluch nasluch;
//	NasluchLista nasluchlista;
	Ramka ramka;
	public Chat chat;
	Wysyl wysyl;
	public boolean connection = false;
	
	public LinkedList<Chat> listachatow = new LinkedList<Chat>();
	LinkedList<String> listauserow = new LinkedList<String>();	
	
	public Obsluga(Ramka ramka)
	{
		this.ramka = ramka;
	}
	
	public void polacz(String adres)
	{
	
		try 
		{
			System.out.println("Adres: " + adres);
			gniazdo = new Socket(adres, 6660);
			
			System.out.println("Gniazdo: " + gniazdo);
			
			nasluch = new Nasluch(gniazdo, this);
//			nasluchlista = new NasluchLista(gniazdo, this);
			wysyl = new Wysyl(gniazdo);
			connection = true;
		} 
		catch (UnknownHostException e) 
		{			
			System.err.println("unknown host: \n" + e);
			wyswietl("Próba połączenia do nieznanego hosta.");
			ramka.okienko("dialog", "Próba połączenia do nieznanego hosta. ");
			ramka.polacz.setEnabled(true);
		} 
		catch (ConnectException ce)
		{
			System.err.println("Odmowa połączenia: \n" + ce);
			wyswietl("Odmowa połączenia lub serwer jest offline, spróbuj ponownie");
			ramka.okienko("dialog", "Odmowa połączenia lub serwer jest offline, spróbuj ponownie");
			ramka.polacz.setEnabled(true);
		}
		catch (IOException e) 
		{		
			System.err.println("Błąd IO: \n" + e + "\n\n");
			ramka.okienko("dialog", "Błąd IO");
			e.printStackTrace();
			ramka.polacz.setEnabled(true);
			
		}
		
	}
	
	public void zakoncz()
	{
		
		try
		{
			nasluch.we.close();
			wysyl.wy.close();
			gniazdo.close();
		}
		catch(IOException ie)
		{
			System.out.println("<Uzytkownik "+imie+ " > Problem zamkniecia gniazda");
		}
		ramka.polacz.setEnabled(true);
		wyswietl("Utracono połączenie z serwerem, spróbuj połączyć się jeszcze raz");
	}
	
	public void wyslij(String text)
	{
		wysyl.wysylaj("@@"+text);
	}

	public void sprawdztext(String text)
	{
		
		String key;
		try
		{
			key = text.substring(0, 2);
		}
		catch(StringIndexOutOfBoundsException se)
		{
			key = "";
		}
		if (key.equalsIgnoreCase("??"))
		{
			String txt = text.substring(2, text.length());
			System.out.println("od hosta: " + txt + "\n");
			wysyl.wysylaj("??"+imie);	
		}
		else if (text.contains("/userlist"))
		{
			if (text.substring(0, 9).equals("/userlist"))
			{
				System.err.println(text.substring(0, 9));
				System.err.println(text.substring(0, 2));
				pobierzliste(text);
			}	
		}
		else
			wyswietl(text);
			
//		else 
//			wysylaj.wysylaj("@@"+text);
	}
	
	public void wyswietl(String text)
	{
		for (Iterator i = listachatow.iterator(); i.hasNext();)
		{
			chat = (Chat)i.next();
			chat.jtaRozmowa.append(text+"\n");
		}
	}
	public void pobierzliste(String lista)
	{
		int start = 10,
			end ;
		
		char znak;
		
		for (end = 10; end < lista.length(); end++ )
		{
			znak = lista.charAt(end);
			if (lista.charAt(end) == ',' && lista.charAt(end+1) == ' ')
			{
				listauserow.add(lista.substring(start, end));
				start = end+2;
				continue;
			}
//			if (znak == ' ')
//			{
//				start = end;
//				continue;		
//			}
		}
		
//		chat.jListaUzytkownikow.removeAll();
		
		for (Iterator i = listachatow.iterator(); i.hasNext();)
		{
			chat = (Chat)i.next();
			chat.jListaUzytkownikow.setListData(listauserow.toArray());
		}
		listauserow.clear();
	}
	
}

0

Piszesz o problemie z funkcją destroy(), a takiej funkcji w aplecie nie ma. Powinieneś w aplecie zaimplementować tę funkcję i w niej zamykać połączenie.
pozdrawiam

0

Możesz sprecyzować swoją odpowiedź? Mi chodziło o funkcje sterujące cyklem życia appletu


public void init()
{
}

public void start()
{
}

public void stop() 
{
}
	
public void destroy() 
{
}

Pogrzebałem troszkę przy programie. Otóż jeśli wybiorę sobie w applecie ocpcję zakończ połączenie

public void actionPerformed(ActionEvent e) {
                if (e.getActionCommand().equals("polacz") )
            {
                        okienko("loguj");
            }
                if (e.getActionCommand().equals("zamknij") )
            {
                        zakoncz();
            }
       
        }     

to wszystko pieknie smiga w Internet explorerze, Gniazdo ulaga zamknieciu.
Taka sama operacja ale w firefoxie sypie mi krytykiem.

Exception in thread "AWT-EventQueue-8" java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkExit(Unknown Source)
at java.lang.Runtime.exit(Unknown Source)
at java.lang.System.exit(Unknown Source)
at GUI.Ramka.actionPerformed(Ramka.java:144)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

nie mam pojęcia co z tym zrobić. W applet viewer też wszystko działa w porządku. Czy wina może leżeć po stronie przeglądarki??

0
  1. Chodziło mi o to, żeby napisać metodę destroy() i w niej zamykać połączenie (o ile jeszcze jest otwarte).
  2. Grzebałeś w kodzie i nie wiem czy to co napiszę jest jeszcze aktualne, ja bym dał dwie wersje metody
    zakoncz(), jedna zamyka ostatecznie (bez komunikatu o możliwości ponownego połączenia)- wywoływana
    przez destroy(), druga wywoływana przez użytkownika
  3. Komunikat o błędzie sugeruje, że w aplecoe jest wywołana metoda System.exit(). Może w tym jest
    przyczyna błędu.
    pozdrawiam
0

W celach testowych napisałem aplet zawierający System.exit(), już apletviewer rzucił wyjątkiem identycznym z twoim. W przeglądarkach już nie sprawdzałem.
pozdrawiam

0

Dzięki za pomoc :)

W końcu mi się udało...

problem tkwił w zamykaniu gniazda i strumieni w funkcji zakończ()

zostawiłem tylko zamykanie gniazda i wszystko działa :)

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