Przyk�adowe zastosowania j�zyka Java

Aplet DwaZegary

Aplet DwaZegary ilustruje niekt�re mo�liwo�ci Javy takie, jak: wielow�tkowo��, wsp�praca z sieci� Internet oraz z przegl�dark�, w kt�rej wy�wietlana jest strona WWW zawieraj�ca aplet. Wykorzystano tak�e poj�cie strumieni oraz klasy i komponenty AWT, do kt�rych nale��: panele, przyciski, zdarzenia, zarz�dcy widok�w.

W aplecie tym ��czymy si� z serwerem, z kt�rego zosta�a za�adowana strona go zawieraj�ca. Z tego serwera odczytujemy dat� i czas (us�uga 'dtime'), nast�pnie odczytujemy dat� i czas na naszym komputerze. Te informacje s� wykorzystane przy tworzeniu dwu w�tk�w, odpowiadaj�cych za: rysowanie odpowiednio: zegara wy�wietlaj�cego czas odczytany z serwera i zegara wy�wietlaj�cego czas lokalny. Dodatkowo u do�u okna znajduje si� przycisk, po naci�ni�ciu kt�rego mamy mo�liwo�� wys�ania poczty email, dzi�ki wykorzystaniu w�a�ciwo�ci przegl�darki. Gdy w u�ytej tu metodzie showDocument (opis, patrz: Przyk�ad 2.44):

showDocument(new URL("mailto:arturt@friko.onet.pl"),"_self");

zmienimy pierwszy parametr na adres strony WWW, naci�ni�cie przycisku spowoduje jej wy�wietlenie w przegl�darce.

Apletu w trakcie dzia�ania przedstawia poni�sza ilustracja:

Ilustracja 4-1Wygl�d apletu DwaZegary

Aplet korzysta z us�ugi 'dtime', us�uga ta umo�liwia sprawdzenie aktualnego czasu i daty na komputerze, z kt�rym sie po��czyli�my.

Dok�adny opis us�ugi mo�na znale�� w dokumencie RFC867. Og�lnie, korzysta ona z portu nr 13. Komunikacja polega na nawi�zaniu po��czenia z serwerem i przes�aniu przez niego informacji. Potem nast�puje przerwanie po��czenia.

Tekst apletu zamieszczono poni�ej:

import java.util.Date;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class DwaZegary extends java.applet.Applet implements Runnable
{
// program napisano tak, aby �atwo mo�na by�o zwi�kszy� liczb� 
// rysowanych zegar�w 
	static int m_nLiczbaZegarow = 2;	
	Date daty[];
	WatekZegara zegary[];
	Thread    watki[];
	Thread    watekGlowny;
	int    m_nLiczbaWatkowNaStarcie;
	//adresy, �r�d�a daty i czasu
	public String zrodloDanych[] = {"friko.onet.pl", "czas lokalny"}; 

	public void init()
	{
		// u�yjemy tej zmiennej p�niej aby sprawdzi� czy wszystkie 
		// w�tki zosta�y zabite
		m_nLiczbaWatkowNaStarcie = Thread.activeCount();
		// ustawienie zarz�dcy rozmieszczenia; zegary b�d� dodawane 
		// na prawo od ostatniego dodanego 
		setLayout(new BorderLayout());
		// utworzenie panelu zawieraj�cego zegary 
		Panel panel = zegaryGridLayoutPanel();		
		
		// utworzenie tablic zawieraj�cych: 
		// 1 w�tki rysuj�ce zegary,
		zegary = new WatekZegara[m_nLiczbaZegarow];
		// 2 w�tki kontroluj�ce wykonanie w�tk�w typu WatekZegara,
		watki = new Thread[m_nLiczbaZegarow];
		// 3 informacj� o czasie i dacie
		daty = new Date[m_nLiczbaZegarow];

		// w tym bloku, czytane s� dane z serwer�w (oraz czas lokalny) 
		for (int numerSerwera = 0; numerSerwera < m_nLiczbaZegarow; numerSerwera++)
		{
			if(zrodloDanych[numerSerwera].compareTo("czas lokalny") != 0)
			{
				try 
				{
					Socket gniazdko = new Socket(zrodloDanych[numerSerwera] ,13 );
					DataInputStream dis = new DataInputStream(gniazdko.getInputStream());	
					daty[numerSerwera]= new Date(dis.readLine());
					gniazdko.close();
				} 
				catch(IOException ioe)
				{
					zrodloDanych[numerSerwera] = 
						"blad przy polaczeniu z "+zrodloDanych[numerSerwera];
					daty[numerSerwera] = new Date(97,01,02,11,59,59);
				}
				catch (Exception e)
				{
					zrodloDanych[numerSerwera] = 
						"blad dla "+zrodloDanych[numerSerwera];
					daty[numerSerwera] = new Date(97,01,02,11,59,59);
				}
				finally
				{
					// inicjalizacja w�tk�w rysuj�cych zegary i dodanie 
					// zegara do panelu
					inicjujZegar(numerSerwera, panel);
				}
			}
			else
			{   // inicjalizacja pozosta�ych zegar�w
				daty[numerSerwera] = new Date();			
				inicjujZegar(numerSerwera, panel);
			}
		}
		add("North",panel);
		Button wyslanieWiadomosci = 
				new Button("Autor: Artur Tyloch  (arturt@friko.onet.pl)");
		add("Center",wyslanieWiadomosci);
		wyslanieWiadomosci.addActionListener(new ActionListener() 
			{
				public void actionPerformed(ActionEvent evt) 
				{
					try
					{	
						getAppletContext().showDocument(
								new URL("mailto:arturt@friko.onet.pl"),"_self");
					}
					catch(Exception e){}
				}
			}
			);
	}
	Panel zegaryGridLayoutPanel()
	{
		Panel tmpPanel = new Panel();
		tmpPanel.setLayout(new GridLayout(1,m_nLiczbaZegarow));
		return tmpPanel;
	}

	// w metodzie tej tworzymy nowy w�tek dla ka�dego zegara 
	// i dodajemy go do panelu
	void inicjujZegar(int x, Panel zegarPanel) 
	{
		zegary[x]=new WatekZegara(daty[x], true, zrodloDanych[x]);		
		zegary[x].resize(size().width,(int)(size().height/1.2));
		zegarPanel.add(zegary[x]);
		watki[x]=new Thread(zegary[x]);
	}
	public void start()
	{
		// uruchomienie wszystkich w�tk�w zegar�w
		for (int x = 0; x < m_nLiczbaZegarow; x++)
			watki[x].start();
		// utworzenie w�tku g��wnego, u�ywanego do monitorowania
		// stanu zegar�w 
		watekGlowny= new Thread (this);
		watekGlowny.start();
	}
	public void stop()
	{	
		watekGlowny.stop();	
	}
	public void run()
	{	
		// wykonanie p�tli do czasu a� wszystkie zegary zako�cz� 
		// swoje dzia�anie 
		while(Thread.activeCount() > m_nLiczbaWatkowNaStarcie+2)
		{
			try
			{	
				watekGlowny.sleep(10);	
				repaint();
			}  
			catch (InterruptedException e)
			{	
				System.out.println("watekGlowny was interrupted");	
			}
		}
		stop();	
		destroy();
	}
}

W klasie WatekZegara zdefiniowano metody odpowiedzialne za rysowanie pojedynczego zegara:

import java.util.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Color;

public class WatekZegara extends java.awt.Canvas implements Runnable 
{
	// wsp�rzedne rysowanych wskaz�wek
	private int m_nOstatnieXS=0, m_nOstatnieYS=0, m_nOstatnieXM=0, m_nOstatnieYM=0, m_nOstatnieXH=0, m_nOstatnieYH=0;
	// ostatnio wy�wietlany czas i data
	private String m_OstatniaData = null;
	// r�nica pomi�dzy czasem lokalnym a czasem na serwerze
	private long m_lRoznica = 0;
	// pole danych okre�laj�ce czy wy�wietlamy czas lokalny, 
	// czy czas serwera
	private boolean m_bZdalne;
	private String m_informacja;

	WatekZegara(Date d, boolean Zdalne, String info)
	{
		Date localD = new Date();
		if ( localD != d) 
			m_lRoznica = localD.getTime() - d.getTime();
		m_OstatniaData = d.toLocaleString();
		m_bZdalne = Zdalne;
		m_informacja = info;
		
		m_nOstatnieXS=70;
		m_nOstatnieYS=m_nOstatnieXS;
		m_nOstatnieXM=m_nOstatnieXS;
		m_nOstatnieYM=m_nOstatnieXS;
		m_nOstatnieXH=m_nOstatnieXS;
		m_nOstatnieYH=m_nOstatnieXS;
	}
	
	public void run()
	{
		while (true) 
		{
			repaint();
			// u�pienie w�tku, aby umo�liwi� przerysowania apletu
			try 
			{
				Thread.currentThread().sleep(1000);
			} 
			catch (InterruptedException e){ }
		}		
	}	

	public void update(Graphics g) 
	{
		// nie ma efektu mrugania (domniemana metoda update 
		// czy�ci pulpit kolorem t�a, a nast�pnie rysuje aplet),
		// tu w metodzie paint stare wskaz�wki s� zamazywane i 
		// nie ma k�opotu z mruganiem rysowanego obrazu zegar�w
		paint(g);
	}

	public synchronized void paint(Graphics g) 
	{	
	
		Date dat = new Date();
		if (m_bZdalne) 
			dat = new Date(dat.getTime()-m_lRoznica); 
		rysujZegar(dat.getSeconds(), dat.getMinutes(), dat.getHours(), size().width/2, 70, dat.toLocaleString(), g);	

		g.setFont(new Font("Helvetica", Font.BOLD, 12));
		g.drawString("Czas:",20 , 165);
		g.drawString(m_informacja,20 , 185);

		g.setFont(new Font("Courier", Font.ITALIC, 10));
		g.drawString("autor: Artur Tyloch",20 , 195);

		g.draw3DRect(2,2,size().width - 4,size().height - 4,true); 
		g.drawRoundRect(5,5,size().width - 10,size().height - 10, 45, 50);
	}

	synchronized private void rysujZegar(int s, int m, int h,
					 int xcenter, int ycenter, String dzis, Graphics g)
	{	
		int xh, yh, xm, ym, xs, ys;
		xs = (int)(Math.cos(s * 3.14f/30 - 3.14f/2) * 45 + xcenter);
		ys = (int)(Math.sin(s * 3.14f/30 - 3.14f/2) * 45 + ycenter);
		xm = (int)(Math.cos(m * 3.14f/30 - 3.14f/2) * 40 + xcenter);
		ym = (int)(Math.sin(m * 3.14f/30 - 3.14f/2) * 40 + ycenter);
		xh = (int)(Math.cos((h*30 + m/2) * 3.14f/180 - 3.14f/2) * 30 + xcenter);
		yh = (int)(Math.sin((h*30 + m/2) * 3.14f/180 - 3.14f/2) * 30 + ycenter);
		// Rysowanie ko�a i liczb
  	  g.setFont(new Font("Courier", Font.BOLD, 14));
  	  g.setColor(Color.blue);
	  g.drawOval(xcenter - 50,ycenter -50 ,100,100);
	  g.setColor(Color.yellow);
	  g.fillOval(xcenter - 45,ycenter -45 ,90,90);	  

  	  g.setColor(Color.darkGray);
  	  g.drawString("9",xcenter-45,ycenter+3); 
  	  g.drawString("3",xcenter+40,ycenter+3);
  	  g.drawString("12",xcenter-5,ycenter-37);
  	  g.drawString("6",xcenter-3,ycenter+45);

  	  // wymazanie, gdy zachodzi taka potrzeba i przerysowanie
  	  g.setColor(Color.yellow/*getBackground()*/);
	  if (xs != m_nOstatnieXS || ys != m_nOstatnieYS) 
	  {
    	  g.drawLine(xcenter, ycenter, m_nOstatnieXS, m_nOstatnieYS);
		  g.setColor(getBackground());
   		  g.drawString(m_OstatniaData, 20 , ycenter + 75);
		  g.setColor(Color.yellow/*getBackground()*/);
  	  }
  	  if (xm != m_nOstatnieXM || ym != m_nOstatnieYM) 
	  {
		  g.drawLine(xcenter, ycenter-1, m_nOstatnieXM, m_nOstatnieYM);
		  g.drawLine(xcenter-1, ycenter, m_nOstatnieXM, m_nOstatnieYM); 
	  }
  	  if (xh != m_nOstatnieXH || yh != m_nOstatnieYH) 
	  {
    	  g.drawLine(xcenter, ycenter-1, m_nOstatnieXH, m_nOstatnieYH);
		  g.drawLine(xcenter-1, ycenter, m_nOstatnieXH, m_nOstatnieYH); 
	  }
  	  g.setColor(Color.darkGray);
  	  g.drawString(dzis, 20, ycenter + 75);  
  	  g.drawLine(xcenter, ycenter, xs, ys);
  	  g.setColor(Color.blue);
  	  g.drawLine(xcenter, ycenter-1, xm, ym);
  	  g.drawLine(xcenter-1, ycenter, xm, ym);
  	  g.drawLine(xcenter, ycenter-1, xh, yh);
  	  g.drawLine(xcenter-1, ycenter, xh, yh);
  	  m_nOstatnieXS=xs; m_nOstatnieYS=ys;
  	  m_nOstatnieXM=xm; m_nOstatnieYM=ym;
  	  m_nOstatnieXH=xh; m_nOstatnieYH=yh;
  	  m_OstatniaData = dzis;
  }
}

Aplet MailAplet

W aplecie MailAplet pokazano wykorzystanie protoko�u SMTP (ang. Simple Mail Transfer Protocol) do wys�ania poczt� e-mail z apletu pod zadany adres.

Po wczytaniu przez przegl�dark� strony WWW zawieraj�cej ten aplet, wysy�any jest list pod adres okre�lony przez pole danych o nazwie adresat. W polu 'Subject' e-mail'a wysy�ana jest informacja o adresie IP osoby przegl�daj�cej stron� WWW. Do pobrania adresu IP u�yto metody statycznej getLocalHost klasy InetAddress.

Dok�adny opis protoko�u mo�na znale�� w dokumencie RFC821. Og�lnie, korzysta on z portu nr 25.

Opis komunikacji:

		Klient: MAIL <SPACJA> FROM:<adres nadawcy> <CRLF>
		Serwer: 250 <komunikat> 
				K: RCPT <SPACJA> TO:<adres odbiorcy> <CRLF>
				S: 250 <komunikat>
				K: DATA <CRLF>
				S: 354 <komunikat2>
				K: Jakas przykladowa tresc listu ....
				K: ... itd. itd. itd. 
				K: <CRLF>.<CRLF> 
				S: 250 <komunikat>

W programie nie interesuje si� tym, co wysy�a serwer, bo zak�adam, ze podaje prawdziwe dane. Poni�ej przedstawiono kod apletu:

import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
public class MailAplet extends Applet
{
	String m_mojGosc = null;
	String adresat = "arturt@priv.onet.pl";

	public void init()
	{
    	resize(320, 40);
		try 
		{
			System.out.println("Przygotowanie listu\n");
			Socket socket = new Socket(getCodeBase().getHost(),25);   
			//odpowiedzi serwera mo�na sprawdzi�, gdy  zadeklarujemy: 
			//DataInputStream dis = 
			//					new DataInputStream(socket.getInputStream());
			// i b�dziemy je interpretowa� 

			DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
			dos.writeBytes("MAIL FROM:<zieloni@uop.warszawa.gov.pl>\n");
			dos.writeBytes("RCPT TO:<"+adresat+">\n");
			dos.writeBytes("DATA\r\n");
			try
			{ 
				m_mojGosc=InetAddress.getLocalHost().toString();
			}
			catch (UnknownHostException e)
			{
				m_mojGosc=e.toString();				
			}
			dos.writeBytes("Subject: GOSC: "+m_mojGosc+"\n\n");
			dos.writeBytes("Dzis odwiedzil:\r\n");
			dos.writeBytes(m_mojGosc+"\r\n");
			dos.writeBytes(".\r\n.\n\n.\nQUIT");
			dos.flush();
			System.out.println("List zostal wyslany");
			socket.close();
		} 
		catch(IOException e)
		{
			System.out.println("BLAD !!!");
		}
	}
	// wy�wietlenie w oknie apletu informacji o wys�aniu e-mail'a
	public void paint(Graphics g)
	{
		g.drawString("Czesc: "+m_mojGosc, 10, 20);
		g.drawString("Mail z informacja o twojej wizycie zostal" + " wyslany do: "+adresat, 10, 30);
	}
}

Zauwa�my, ze mo�na w ten spos�b wys�a� list jako "ktokolwiek". Wystarczy tylko w "MAIL FROM:<adres>" poda� dowolny (nawet nieistniej�cy) adres. Tym sposobem mo�na podszy� si� pod ka�dego !

A oto, kilka nag��wk�w (pole Subject) list�w jakie otrzyma�em, po umieszczeniu apletu na stronie WWW "http://friko.onet.pl/po/arturt/":

GOSC: robert/195.116.127.24
GOSC: pcjura.comarch.pl/195.116.125.114
GOSC: fornax/150.254.25.38
GOSC: wks620.inform.pucp.edu.pe/200.16.7.180  
GOSC: w014-3.ppcor.org.pl/190.59.76.23
GOSC: lala.waw.ids.edu.pl/195.117.3.20
GOSC: imul-043.uni.lodz.pl/193.59.60.56
GOSC: ds3pc94.pol.lublin.pl/194.92.19.94
GOSC: quake.tx.iex.com/192.153.191.251
GOSC: ppp.sylaba.poznan.pl/150.254.152.163
GOSC: Dolar.it.com.pl/195.116.134.101
GOSC: parkds.hscom.co.kr/150.30.50.32

Na podobnych zasadach mo�na napisa� w Javie ka�d� us�ug� sieciow�.

Pisanie sieciowych aplikacji w Javie jest bardzo proste. Java dostarcza pakiet java.net, w kt�rym s� zdefiniowane wszystkie niezb�dne klasy do obs�ugi komunikacji po��czeniowej (TCP) i bezpo��czeniowej (UDP), zar�wno dla aplikacji klienckich jak i serwerowych.