Java


12. Programowanie sieciowe

12.1. Sterowanie przeglądarką

Najprostszym i najczęściej stosowanym zabiegiem jest kojarzenie w apletach przycisków z adresami w Internecie. Pozwala to wyświetlać strony WWW za pomocą naciśnięcia przycisku.

Do przechowywania adresów służy klasa URL dostępna w pakiecie java.net. Obiekty tej klasy można tworzyć na różne sposoby:

Na przykład, obiekt zawierający adres strony IPPT PAN można utworzyć w taki sposób:

String url = ”http://www.ippt.gov.pl”;

try { URL adres = new URL ( url ); }

catch ( MalformedURLException e ) {

System.out.println ( ”Błędny adres URL” );

}

Po utworzeniu obiektu można go wyświetlić w przeglądarce. Służą do tego dwie metody klasy URL:

getAppletContext ( ) oraz showDocument ( ).

Obiekt klasy AppletContext zawiera informacje o środowisku, w którym działa aplet, czyli o przeglądarce. Po utworzeniu takiego obiektu zlece­niem

AppletContext ac = getAppletContext ( );

możemy zarówno sterować przeglądarką, jak i komunikować się z innymi apletami. Na przykład, możemy wyświetlić stronę WWW o adresie adresURL za pomocą zlecenia

ac.showDocument ( adresURL );

Przykładowy aplet Ulubione tworzy 3 przyciski, które wywołują wybrane strony WWW:

1) informację o trasach zjazdowych w Szczyrku;

2) serwer pocztówek;

3) stronę domową Javy.

Przykład

import java.awt.*;

import java.awt.event.*;

import java.net.URL;

import java.net.MalformedURLException;

public class Ulubione extends java.applet.Applet

implements ActionListener {

final int MAX = 4; // liczba przycisków

final int H = 30; // odstęp w poziomie

final int V = 0; // odstęp w pionie

final int D = 10; // margines

final String [ ] [ ] zakładki = {

{ "Szczyrk", "http://www.petex.bielsko.pl/wyciag/szczyrk/" },
{ "Pocztówki", "http://www.rava.com.pl/kartki/" },
{ "Java", "http://java.sun.com" },
{ "Koniec", " " }

};

Button przyciski [ ] = new Button [ MAX ];

public Insets getInsets ( ) {

return new Insets ( D, D, D, D );

}

Button dodajPrzycisk ( String nazwa ) {

Button przycisk = new Button ( nazwa );

add( przycisk );

przycisk.addActionListener ( this );

return przycisk;

}

public void actionPerformed ( ActionEvent e ) {

Button przycisk = ( Button ) e.getSource ( );

String nazwa = przycisk.getLabel ( );

if ( nazwa != zakładki [ MAX ] [ 0 ] ) {

wyświetl ( nazwa );

}

else

this.setVisible ( false );

}

public void init ( ) {

setBackground ( Color.blue );

setLayout ( new FlowLayout ( FlowLayout.CENTER,
H, V ) );

for ( int i = 0; i < MAX; i++ ) {

przyciski [ i ] = dodajPrzycisk ( zakładki [ i ] [ 0 ] );

}

}

void wyświetl ( String name ) {

URL adr = null;

for ( int i = 0; i < 3; i++ ) {

if ( name.equals ( zakładki [ i ] [ 0 ] )) {

try { adr = new URL ( zakładki [ i ] [ 1 ] ); }

catch ( MalformedURLException e ) {

System.out.println ( "Zły adres: " + adr );

}

}

}

if ( adr != null )

getAppletContext ( ).showDocument ( adr );

}

}

12.2. Zdalny dostęp do plików

Klasy pakietu java.net pozwalają nawiązywać połączenia ze zdalnym komputerem i pobierać z niego pliki. Należy przy tym pamiętać, że aplet ma dostęp do lokalnego dysku jedynie na tym serwerze, na którym sam jest zainstalowany.

0x08 graphic

Metoda openStream ( ) klasy URL otwiera połączenie sieciowe z plikiem o podanym adresie URL. Protokół połączenia (np. ftp lub http) określony jest w adresie URL. Metoda ta zwraca obiekt klasy InputStream, który można skonwertować do postaci

BufferedInputStream lub

DataInputStream.

Oto jak można zdalnie przeczytać plik o adresie mojURL:

try {

InputStream we = mójURL.openStream ( );

DataInputStream dane = new DataInputStream
( new BufferedInputSteam ( we ) );

String line;

while ( ( line = dane.readLine ( ) ) != null ) {

System.out.println ( line );

}

}

catch ( IOException e ) {

System.out.println ( ”Błąd wejścia/wyjścia: ” +
e.getMessage ( ) );

}

Przykładowy aplet CzytajZdalnie łączy się z podanym serwerem, otwiera na nim plik tekstowy i wyświetla zawartość tego pliku na ekranie. Występuje w nim pomocnicza klasa URLConnection, której metoda connect ( ) powoduje otwarcie połączenia sieciowego.

Przykład

import java.awt.*;

import java.io.*;

import java.net.*;

public class CzytajZdalnie extends java.applet.Applet

implements Runnable {

URL adres;

Thread wątek;

TextArea tekst = new TextArea ( "Pobieranie tekstu ..." );

public void init ( ) {

setLayout ( new GridLayout ( 1, 1 ) );

String url =
"http://www.ippt.gov.pl/~abork/testowy.txt";

try { this.adres = new URL ( url ); }

catch ( MalformedURLException e ) {

System.out.println ( "Błędny adres: " + adres );

}

add ( tekst );

}

// pominięte metody start ( ), stop ( )

public void run ( ) {

URLConnection połączenie = null;

BufferedReader dane = null;

String wiersz;

StringBuffer buf = new StringBuffer ( );

try {

połączenie = this.adres.openConnection ( );

połączenie.connect ( );

tekst.setText ( "Otwieram połączenie ..." );

dane = new BufferedReader ( new
InputStreamReader ( połączenie.getInputStream ( ) ) );

tekst.setText ( "Czytam dane ..." );

while ( ( wiersz = dane.readLine ( ) ) != null ) {

buf.append ( wiersz + "\n" );

}

tekst.setText ( buf.toString ( ) );

}

catch ( IOException e ) {

System.out.println ( "Błąd wejścia/wyjścia: " +
e.getMessage ( ) );

}

}

}

12.3. Architektura klient-serwer

Wiele programów działających w środowisku sieciowym działa na zasadzie współpracy par klient-serwer:

0x08 graphic

W takiej parze serwer czeka na zgłoszenie pewnego zapotrzebowania przez klienta (przykładem może być prośba o przesłanie zawartości skrzynki pocztowej). Po otrzymaniu zgłoszenia serwer wykonuje odpo­wiednią czynność i wraca do stanu oczekiwania.

Zwykle komunikacja pomiędzy serwerem i klientem odbywa się za pośrednictwem protokołu sieciowego TCP/IP z wykorzystaniem pojęcia gniazd (sockets). Pakiet java.net zawiera szereg klas służących do tworzenia i obsługi gniazd.

Gniazdo po stronie klienta tworzymy jako obiekt klasy Socket:

Po utworzeniu gniazda możemy przypisać mu strumienie wej­ścia/wyjścia:

DataInputStream in = new DataInputStream
( new BufferedInputStream
( gniazdo.getInputStream ( ) ) );

DataOutputStream in = new DataOutputStream
( new BufferedOutputStream
( gniazdo.getOutputStream ( ) ) );

Po zakończeniu transmisji wypada zamknąć połączenie metodą gniazdo.close ( ).

Gniazdo po stronie serwera otwieramy zleceniem

Zgłoszenie klienta akceptowane jest za pośrednictwem metody
accept ( ).

Para aplikacji Klient-Serwer ilustruje implementowanie takiej architektury w Javie.

Program Serwer wykonuje następujące czynności:

  1. czeka na zgłoszenie klienta;

  2. akceptuje zgłoszenie;

  3. przesyła klientowi losowo wybrane pytanie;

  4. czeka na odpowiedz;

  5. sprawdza jej poprawność i przesyła odpowiedni komunikat do klienta;

  6. pyta klienta, czy ma zadać następne pytanie;

  7. czeka na odpowiedz;

  8. jeżeli odpowiedź jest pozytywna, to wraca do kroku 3;

  9. w przeciwnym razie wraca do kroku 1.

Pytania zadawane przez serwer i odpowiedzi uznawane za prawidłowe zapisane są w pomocniczym pliku Pytania.txt:

Co spowodowało powstanie kraterów na Księżycu?

meteoryty

W jakiej odległości od Ziemi jest księżyc (w milach)?

239000

W jakiej odległości od Ziemi jest Słońce(w milionach mil)?

93

Czy Ziemia jest idealną sferą?

nie

Jaka jest wewnętrzna temperatura Ziemi (w stopniach F)?

9000

Jakijest wiek Ziemi (w milionach lat)?

4600

Z jaką prędkością porusza się światło (w milach na sekundę)?

186300

Czy Słońce się porusza?

tak

Jaka jest nazwa świetlnej smugi, którą czasami widać na niebie?

Droga Mleczna

Czy Galaktyka się obraca?

tak

Przykład

import java.io.*;

import java.net.*;

import java.util.Random;

public class Serwer extends Thread {

private static final int PORTNUM = 1234;

private static final int CZEKAJ_NA_KLIENTA = 0;

private static final int CZEKAJ_NA_ODPOWIEDŹ = 1;

private static final int
CZEKAJ_NA_POTWIERDZENIE = 2;

private String [ ] pytania;

private String [ ] odpowiedzi;

private ServerSocket gniazdoSerwera;

private int liczbaPytań;

private int num = 0;

private int stan = CZEKAJ_NA_KLIENTA;

private Random rand = new
Random ( System.currentTimeMillis ( ) );

public Serwer ( ) {

super( "Serwer" );

try {

gniazdoSerwera = new ServerSocket ( PORTNUM );

System.out.println ( "Serwer uruchomiony ..." );

}

catch ( IOException e ) {

System.err.println ( "Nie mozna utworzyc gniazda" );

System.exit ( 1 );

}

}

public static void main ( String [ ] args ) {

Serwer serwer = new Serwer ( );

serwer.start ( );

}

public void run ( ) {

Socket gniazdoKlienta;

// Inicjalizacja tablic pytań i odpowiedzi

if ( !initPytania ( ) ) {

System.err.println ( "Nie udalo sie zainicjalizowac tablic
pytan i odpowiedzi");

return;

}

// Oczekiwanie na połączenie i zadanie pytania

while ( true ) {

// Czekaj an klienta

if ( gniazdoSerwera == null )

return;

try {

gniazdoKlienta = gniazdoSerwera.accept ( );

// Zadanie pytania i pobranie odpowiedzi

BufferedReader we = new BufferedReader ( new InputStreamReader ( gniazdoKlienta.getInputStream ( ) ) );

PrintStream wy = new PrintStream
( new BufferedOutputStream
( gniazdoKlienta.getOutputStream ( ) ), false );

String wierszWe, wierszWy;

// Przesłanie pytania

wierszWy = wczytaj ( null );

wy.println( wierszWy );

wy.flush ( );

// Przetworzenie odpowiedzi

while ( ( wierszWe = is.readLine ( ) ) != null ) {

wierszWy = wczytaj ( wierszWe );

wy.println ( wierszWy );

wy.flush ( );

if ( wierszWy.equals ( "koniec" ) )

break;

}

// Sprzątanie

wy.close ( );

we.close ( );

gniazdoKlienta.close ( );

}

catch (Exception e) {

System.err.println ( "Blad: " + e );

e.printStackTrace ( );

}

}

}

private boolean initPytania ( ) {

try {

File plikWe = new File ( "Pytania.txt" );

FileInputStream strumieńWe = new
FileInputStream ( plikWe );

byte [ ] dane = new byte [ ( int ) plikWe.length ( ) ];

// Wczytaj pytania i odpowiedzi do tablicy bajtów

if ( strumieńWe.read ( dane ) <= 0 ) {

System.err.println ( "Nie mozna odczytac pytan i
odpowiedzi");

return false;

}

// Zobacz ile par pytań i odpowiedzi przeczytano

for ( int i = 0; i < dane.length; i++ )

if ( dane [ i ] == ( byte ) '\n' )

liczbaPytań ++;

liczbaPytań /= 2;

pytania = new String [ liczbaPytań ];

odpowiedzi = new String [ liczbaPytań ];

// Załaduj pytania i odpowiedzi od tablic napisów

int start = 0, index = 0;

boolean jestP = true;

for ( int i = 0; i < dane.length; i++ )

if ( dane [ i ] == ( byte ) '\n' ) {

if ( jestP ) {

pytania [ index ] =
new String ( dane, 0, start, i - start - 1 );

jestP = false;

}

else {

odpowiedzi [ index ] =
new String ( dane, 0, start, i - start - 1 );

jestP = true;

index++;

}

start = i + 1;

}

}

catch ( FileNotFoundException e ) {

System.err.println ( "Nie mozna odnalezc pliku" );

return false;

}

catch ( IOException e ) {

System.err.println ( "Blad przy probie odczytu pliku" );

return false;

}

return true;

}

String wczytaj ( String inStr ) {

String outStr = "";

switch ( stan ) {

case CZEKAJ_NA_KLIENTA:

// Zadaj pytanie

outStr = pytania [ num ];

stan = CZEKAJ_NA_ODPOWIEDŹ;

break;

case CZEKAJ_NA_ODPOWIEDŹ:

// Sprawdź odpowiedź

if ( inStr.equalsIgnoreCase ( odpowiedzi [ num ] ) )

outStr = "Odpowiedz poprawna!
Nastepne pytanie? ( t/n )";

else

outStr = "Zle, poprawna odpowiedz to " +
odpowiedzi [ num ] +
". Nastepne pytanie? ( t/n )";

stan = CZEKAJ_NA_POTWIERDZENIE;

break;

case CZEKAJ_NA_POTWIERDZENIE:

// Czy użytkownik chce odpowiadać na następne pytanie?

if ( inStr.equalsIgnoreCase ( "t" ) ) {

num = Math.abs ( rand.nextInt ( ) ) % pytania.length;

outStr = pytania [ num ];

stan = CZEKAJ_NA_ODPOWIEDŹ;

}

else {

outStr = "koniec";

stan = CZEKAJ_NA_KLIENTA;

}

break;

}

return outStr;

}

}

Schemat działania programu Klient jest następujący:

  1. nawiązanie połączenia z serwerem;

  2. oczekiwanie na pytanie;

  3. wyświetlenie pytania i pobranie odpowiedzi użytkownika;

  4. przesłanie odpowiedzi do serwera;

  5. oczekiwanie na odpowiedz serwera;

  6. wyświetlenie tej odpowiedzi i spytanie użytkownika, czy oczekuje dalszych pytań;

  7. odesłanie odpowiedzi użytkownika do serwera;

  8. jeżeli odpowiedz była pozytywna, powrót do kroku 2;

  9. w przeciwnym razie powrót do kroku 1.

Przykład

import java.io.*;

import java.net.*;

public class Klient {

private static final int PORTNUM = 1234;

public static void main ( String [ ] args ) {

Socket gniazdo;

BufferedReader we;

PrintStream wy;

String serwer;

// Sprawdź argumenty wywołania by określić nazwę serwera

if ( args.length != 1 ) {

System.out.println ( "Wywołanie:
java Klient < nazwa serwera > " );

return;

}

else

serwer = args [ 0 ];

// Inicjalizuj gniazda i strumienie

try {

gniazdo = new Socket ( serwer, PORTNUM );

we = new BufferedReader (new InputStreamReader
( gniazdo.getInputStream ( ) ) );

wy = new PrintStream ( gniazdo.getOutputStream ( ) );

// Obsługa danych wprowadzanych przez użytkownika

StringBuffer str = new StringBuffer ( 128 );

String inStr;

int c;

while ( ( inStr = we.readLine ( ) ) != null ) {

System.out.println ( "Serwer: " + inStr );

if ( inStr.equals ( "koniec" ) )

break;

while ( ( c = System.in.read ( ) ) != '\n' )

str.append ( ( char ) c );

System.out.println ( "Klient: " + str );

wy.println( str.toString ( ) );

wy.flush ( );

str.setLength ( 0 );

}

// Zamykanie strumieni i gniazd

wy.close ( );

we.close ( );

gniazdo.close ( );

}

catch ( IOException e ) {

System.err.println ( "Błąd tworzenia gniazda lub błąd
we-wy" );

}

}

}

Adam Borkowski Język programowania „Java” 12−20

Dysk
serwera

Serwer
sieciowy

Internet

Dysk
lokalny

Komputer

zgłoszenie

Klient

Serwer

usługa



Wyszukiwarka

Podobne podstrony:
Java Media FreamWork
java 2
Projekt java
JAVA tablice
Inzynieria oprogramowania w ujeciu obiektowym UML wzorce projektowe i Java iowuje
Java Przewodnik dla poczatkujacych Wydanie V javpp5
zasady grupy, java, javascript, oprogramowanie biurowe, programowanie, programowanie 2, UTK, systemy
praktyczny kurs java NX2M5DXARLEHY6NHXOS5FJHKLI6ACRLQQSDRS2Q
notatki java 08
Praktyczny kurs Java
Java praca domowa 10
java 3 id 226367 Nieznany
Java Coding rules
java object serialization speci Nieznany
java script TY2DWI33KJCAKQBCFPFEFQ736KLTSQZ3F6JQE2Q
JP SS 4 start Java
notatki java 05
java swing
notatki java 07
helion java cwiczenia zaawansow Nieznany

więcej podobnych podstron