Professional Documents
Culture Documents
8-3
Powyszy szkic stosowania metod rodzimych zawiera trzy bloki. Pierwszy z nich
deklaruje metod rodzim, ktra rni si od pozostaych metod tym, e uywany jest
specyfikator native w deklaracji. Drugi blok to kod statyczny adowany przy
interpretowaniu (kompilacji) kodu bajtw pobierajcy bibliotek przechowujcy
realizacj metody rodzimej. Ostatni blok to zastosowanie metody rodzimej.
Zadeklarowanie metody jako native oznacza, e kompilator ma uzna dan metod
jako rodzim zdefiniowan i zaimplementowan poza Jav. Podana w deklaracji
metody rodzimej nazwa jest odwzorowywana pniej na nazw funkcji w kodzie
rodzimym zgodnie z regu:
nazwa -> Java_NazwaPakietu_NazwaKlasy_nazwa, czyli np.
8-4
Jak wida jest to nagwek dla kodu metody rodzimej tworzonego w C/C++.
Zasadniczo mona tworzy implementacje metod rodzimych w innych jzykach ale to
wymaga indywidualnego podejcia (konwersji typw i nazw), std zaleca si
korzystanie jedynie z C/C++ do obsugi metod rodzimych. W zasadniczej czci
nagwka (poza analiz skadni dla C czy C++) zawarto opis metody uywajc do
8-5
8-6
JNIEnv* wskanik interfejsu JNI zorganizowany jako tablica funkcji JNI o konkretnej
lokalizacji. Metoda rodzima wykorzystuje funkcje poprzez odwoanie si do
wskanika JNIEnv*. Przykadowo mona pobra rozmiar macierzy wykorzystujc
funkcj GetArrayLength() poprzez wskanik JNIEnv*:
(...) JNIEnv *env (...) jintArray macierz (...)
jsize rozmiar = (*env)->GetArrayLength(env, macierz);
jobject to kolejny element deklaracji funkcji w JNI. Argument tego typu stanowi
referencj do biecego obiektu; jest odpowiednikiem this w Javie.
Warto tu zauway, e odpowiednikiem metody Javy zadeklarowanej jako native
jest funkcja zawierajca co najmniej dwa argumenty, nawet wwczas gdy metoda nie
zawiera adnego.
jstring lub inne typy argumentw - kolejne argumenty funkcji (argumenty metody
rodzimej).
8-7
8-8
8-10
8-11
IInneettA
Addddrreessss..ggeettA
AlllB
ByyN
Naam
mee((S
Sttrriinngg nnaazzw
waa)),,
IInneettA
Addddrreessss..ggeettLLooccaallH
Hoosstt(());;
Pierwsza metoda tworzy obiekt klasy bazujc na podanej nazwie komputera lub
adresie. Druga metoda jest wykorzystywana wwczas kiedy komputer o danej
nazwie ma wiele adresw IP. Zwracana jest wwczas tablica obiektw typu
InetAddress. Ostania metoda jest wykorzystywana do uzyskania obiektu
reprezentujcego adres komputera lokalnego. Wszystkie metody musz zawiera
deklaracje lub obsug wyjtku UnknownHostException powstajcego w przypadku
braku identyfikacji komputera o podanej nazwie lub adresie. Poniej zaprezentowano
przykadowy program wykorzystujcy prezentowane metody klasy InetAddress.
Przykad 8.4:
//Adresy.java
//Adresy.java
import java.net.*;
public class Adresy{
public static void main(String args[]){
try{
InetAddress a0 = InetAddress.getLocalHost();
System.out.println("Adres komputera "+a0.getHostName()+" to: " +a0);
InetAddress a1 = InetAddress.getByName("biomed.eti.pg.gda.pl");
System.out.println("Adres komputera biomed to: "+a1);
InetAddress a2[] = InetAddress.getAllByName("www.eti.pg.gda.pl");
System.out.println("Adres komputera www.eti.pg.gda.pl to:");
for(int i=0; i<a2.length; i++){
System.out.println(a2[i]);
}
} catch (UnknownHostException he) {
he.printStackTrace();
}
}
}// koniec public class Adresy
identyfikator protokou oraz nazw zasobw. Identyfikator protokou to np. http, ftp,
gopher, rmi czy jdbc. Nazw zasobw stanowi takie elementy jak: nazwa hosta,
nazwa pliku, numer portu, nazwa odwoania (w danym pliku). Tworzc wic obiekt
klasy URL otrzymujemy gotowy wskanik, ktry jest wykorzystywany przez liczne
metody Javy (np. otwieranie obrazka getImage(), tworzenie poczenia w JDBC Connection). W odrnieniu od klasy InetAddress tworzenie obiektw klasy URL
odbywa si poprzez wykorzystanie jednego z licznych konstruktorw. Kady z nich
zwizany jest z koniecznoci obsugi wyjtku MalformedURLException powstajcym
w wypadku problemw z identyfikacj wskazanego w wywoaniu konstruktora
protokou. Liczne konstruktory umoliwiaj podania parametrw adres URL albo
poprzez odpowiednik adresu bdcy tekstem (String) albo poprzez tworzenie tego
adresu z takich elementw jak nazwa protokou, nazwa komputera, port, nazwa pliku,
itp. Przykadowe konstruktory maj posta:
U
RLL((S
Sttrriinngg aaddrreess)) ,,
UR
R
L
(
S
U
Sttrriinngg pplliikk))
Sttrriinngg hhoosstt,, iinntt ppoorrtt,, S
URL(Sttrriinngg pprroottookk,, S
Klasa URL zawiera szereg metod umoliwiajcych filtracj adresu, a wic pobranie
nazwy protokou (getProtocol()), nazwy komputera (getHost()), pliku (getFile()) czy
numeru portu (getPort()). Dodatkowo klasa URL zawiera metody umoliwiajce
wykonywanie poczenia z hostem (tworzone jest gniazdo o czym dalej) i
przesyanie danych. Przykadowy program ukazuje moliwo wykorzystania
funkcjonalnoci klasy URL:
Przykad 8.5:
//Pobiez.java
import java.net.*;
import java.io.*;
public class Pobiez{
public static void main(String args[]){
URL url;
String tekst;
if (args.length !=1) {
System.out.println("Wywoanie: Pobiez URL; gdzie URL to adres zasobw");
System.exit(1);
}
try{
url = new URL(args[0]);
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
while( (tekst=br.readLine()) !=null){
System.out.println(tekst);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}// koniec public class Pobiez
8-13
width=52
(...)
- nasuch,
- akceptacja pocze na danych portach.
Pierwsze cztery funkcje s waciwe dla klienta, serwer rozszerza je o dodatkowe
trzy. W Javie obsug klienta, a wic realizacj pierwszych czterech funkcji dostarcza
klasa Socket; dla serwera przeznaczono klas ServerSocket. Socket (gniazdo) to
dobrze znane pojcie wynikajce z planw stworzenia dostpu do sieci jako do
strumienia danych (strumie wejcia, strumie wyjcia). Koncepcja strumieni miaa
by uniwersalna dla kadego moliwego przepywu danych (z urzdzenia, z pliku, z
sieci). Socket jest wic pewn abstrakcj umoliwiajc przejcie na wyszy poziom i
nie zajmowaniem si takimi zagadnieniami jak rozmiar pakietu, retransmisja pakietu,
typ mediw, itp. Rozwamy teraz zagadnienia zwizane ze stron klienta procesu
komunikacji sieciowej, a wic zapoznajmy si z klas Socket pakietu java.net.
Klasa Socket posiada szereg rnych konstruktorw, z ktrych najbardziej popularne
s:
S
Addddrreessss
Addddrreessss aaddddrreessss,, iinntt ppoorrtt)) -- ggddzziiee aaddddrreessss ttoo oobbiieekktt kkllaassyy IInneettA
Soocckkeett((IInneettA
5
)
,
3
6
5
5
(
0
t
u
o
r
e
r
p
m
n
u
t
p
o
r
,
o
s
t
a
h
z
w
n
a
u
b
l
I
P
bbddccyy aaddrreesseem
m IP lub nazw hosta, port - numer portu (0-65535),
S
w hhoossttaa,, ppoorrtt -Sttrriinngg hhoosstt,, iinntt ppoorrtt)) -- ggddzziiee hhoosstt ttoo tteekksstt oozznnaacczzaajjccyy nnaazzw
Soocckkeett((S
)
.
5
5
3
5
6
(
0
t
u
r
o
p
r
e
nnuum
mer portu (0-65535).
Poniewa poczenie wykonywane przez obiekt klasy Socket moe nie powie si z
rnych przyczyn (np. nie znany host) konieczna jest obsuga wyjtkw.
Klasyczny fragment kodu obsugi klasy Socket pokazano poniej:
ttrryy {{
S
mgg..ggddaa..ppll"",, 8800));;
w..aam
ww
ww
Soocckkeett((""w
wS
Soocckkeett ggnniiaazzddoo== nneew
}}
ccaattcchh ((U
Unnkknnoow
wnnH
HoossttE
Exxcceeppttiioonn ee)) {{
S
Syysstteem
m..eerrrr..pprriinnttllnn((ee));;
}}
ccaattcchh ((IIO
OE
Exxcceeppttiioonn ee)) {{
S
Syysstteem
m..eerrrr..pprriinnttllnn((ee));;
}}
8-15
8-16
if (args.length > 0) {
host = args[0];
}
for (int n = 0; n < 1024; n++) {
try {
gniazdo = new Socket(host, n);
int lokalPort = gniazdo.getLocalPort();
System.out.println("Numer lokalnego portu to:" + lokalPort);
System.out.println("Znalazem serwer na porcie " + n + " komputera: " + host);
}
catch (UnknownHostException e) {
System.err.println(e);
break;
}
catch (IOException e) {
//System.err.println(e);
}
}
}
}// koniec public class SkanerPortow2
8-17
host = args[0];
try {
gniazdo = new Socket(host, 13);
strumienCzasu = new BufferedReader(new InputStreamReader(gniazdo.getInputStream()));
String czas = strumienCzasu.readLine(); //wprowad lini znakw z bufora strumienia
System.out.println("Na "+host+" jest: "+czas);
}
catch (UnknownHostException e) {
System.err.println(e);
}
catch (IOException e) {
System.err.println(e);
}
}
}//koniec public class Zegar
8-18
}
}
catch (UnknownHostException e) {
System.err.println(e);
}
catch (IOException e) {
System.err.println(e);
}
}
}//koniec public class KlientEcho
Program serwera
Przykad 8.10:
//SerwerEcho.java:
import java.net.*;
import java.io.*;
public class SerwerEcho {
public static void main(String[] args) {
ServerSocket serwer;
Socket gniazdo;
String host = "localhost";
BufferedReader strumienEcha, strumienWe;
PrintStream strumienWy;
String echo;
if (args.length > 0) {
host = args[0];
}
try {
serwer = new ServerSocket(7); //stworz serwer pracujacy na porcie 7 biezacego komputera
while(true){ //gwna ptla serwera
try{
while(true){ //gwna ptla poczenia
gniazdo = serwer.accept(); //przyjmuj poczenia i stworz gniazdo
System.out.println("Jest polaczenie");
while(true){
strumienWe = new BufferedReader(new InputStreamReader(gniazdo.getInputStream()));
strumienWy = new PrintStream(gniazdo.getOutputStream());
echo=strumienWe.readLine();
strumienWy.println(echo); //wyslij to co przyszlo
}//od while
}//od while
8-19
}//od try
catch (SocketException e){
System.out.println("Zerwano polaczenie"); //klient zerwa poczenie
}
catch (IOException e) {
System.err.println(e);
}
}//od while
}// od try
catch (IOException e) {
System.err.println(e);
}
}
}//koniec public class SerwerEcho
8.3 Serwlety
Serwlet jest definiowan przez programist klas implementujc interfejs
javax.servlet.Servlet. Zadaniem serwletu jest wykonywanie dziaa w rodowisku
serwera. Oznacza to, e serwlet nie stanowi oddzielnej aplikacji, lecz jego
wykonywanie jest zalene od serwera. Serwlet stanowi zatem odmian apletu, z tym,
e dziaa nie po stronie klienta (w otoczeniu np. przegldarki WWW) lecz po stronie
serwera. Taka forma dziaanie serwleta wymaga od serwera zdolnoci do
interpretacji kodu poredniego Javy oraz moliwoci wykorzystania produktu
wykonanego kodu Javy w obrbie funkcjonalnoci serwera. Interpretacja kodu
poredniego odbywa si najczciej za porednictwem zewntrznej wzgldem
serwera maszyny wirtualnej co wymaga zaledwie prostej konfiguracji serwera.
Zdolno do wykorzystania serwletw przez serwer deklaruj producenci danego
8-20
init(),
service()
destroy()
8-21
GenericServlet
HttpServlet
definiowane kolejno w dwch dostpnych pakietach JSDK API:
javax.servlet
javax.servlet.http.
Korzystajc z przedstawionego modelu mona skonstruowa pierwszy przykad
serwletu:
Przykad 8.11:
//WitajcieServlet.java:
import javax.servlet.*;
import java.io.*;
public class WitajcieServlet extends GenericServlet{
static String witajcie= "Witajcie ! Jestem serwletem!\n";
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
response.setContentLength(witajcie.length());
response.setContentType("text/plain");
PrintWriter pw=response.getWriter());
pw.print(witajcie);
pw.close();
}
}// koniec public class WitajcieServlet
8-23
8-24
8-25
//KlientServlet.java:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class KlientServlet extends HttpServlet {
static String wiad = "Oto nag\u0142\u00F3wki: \n";;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException{
String nazwa, wartosc, nag="";
response.setContentType("text/plain; charset=iso-8859-2");
// dla wersji nowszej od JSDK 2.0 mona ustali lokalizacje:
//response.setLocale(new Locale("pl","PL"));
PrintWriter pw = response.getWriter();
Enumeration e = request.getHeaderNames();
while (e.hasMoreElements()) {
nazwa = (String)e.nextElement();
wartosc = request.getHeader(nazwa);
nag+=(nazwa + " = " + wartosc+"\n");
}
pw.print(wiad+nag);
pw.close();
}
}// koniec public class KlientServlet
Powyszy serwlet jest zdefiniowany dla klasy typu HttpServlet definiujcej szereg
metod obsugujcych protok HTTP. Jedn z usug tego protokou jest pobranie
nagwka i danych GET. Obsuga tej usugi jest moliwa poprzez zastosowanie
metody doGet(), do ktrej s przekazywane obiekty typu HttpServletRequest i
HttpServletResponse. Poniewa wraz z przesyaniem wiadomoci w HTTP przesya
si rwnie nagwek zawierajcy informacje sterujce mona te informacje pobra i
wywietli. Omawiany program pobiera zestaw informacji konfiguracyjnych
pochodzcych
z
nagwkw
wygenerowanych
przez
klienta
usugi
(request.getHeaderNames()). Pobrane informacje s formatowane w postaci
tekstowej zgodnie ze stron kodow iso-8859-2 i s przesyane jako tre informacji
do klienta (respone). W wyniku dziaania tego serwletu klient moe obserwowa w
swojej przegldarce nastpujcy efekt:
Oto nagwki:
Connection = Keep-Alive
User-Agent = Mozilla/4.6 [en-gb] (WinNT; I)
Host = med16:8080
Accept = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding = gzip
Accept-Language = en-GB,en,en-*
Accept-Charset = iso-8859-1,*,utf-8
8-26
Niestety zastosowanie tego typu jest ograniczone poniewa tylko niektre serwery je
umoliwiaj (Java Web ServerTM). Stosowanie dynamicznej kompozycji stron w
obrbie kodu HTML jest obecnie realizowane poprzez technologi Java Server
Pages (JSP).
pw.print(wiad);
pw.close();
W wyniku dziaania
(sformatowany) tekst:
powyszego
programu
mona
uzyska
nastpujcy
pw.print(wiad);
pw.close();
8-31
</html>
8-32
metody obiektu zdalnego tak, jakby byy to metody lokalne. Mechanizm ten jest wic
bardzo wygodny dla programisty. Pojawia si jednak pewien problem. Ot jeli
obiekt jest przekazywany (argument) lub zwracany przez metod zwracana jest w
rzeczywistoci referencja realizowana jako wskanik do pamici organizowanej przez
dan maszyn wirtualn. Wymiana obiektw, a wic referencji pomidzy dwoma
maszynami wirtualnymi przysparza pewien problem: referencja obiektu A, np. 12345
w danej maszynie wirtualnej nie wskazuje tego samego obiektu na innej maszynie
wirtualnej. Rozwizanie tego problemu moe by wykonane na dwa sposoby. Po
pierwsze mona przekaza zdaln referencj obiektu wskazujc na pami zdalnej
maszyny wirtualnej. Oznacza to, e jeeli klient przekazuje jako argument obiekt
zdalny (realizowany na maszynie zdalnej) to w rzeczywistoci przekazuje jego zdaln
referencj czyli zdalny obiekt nigdy nie opuszcza swojej maszyny wirtualnej. Jeeli,
co stanowi drugie rozwizanie, natomiast klient przekazuje swj obiekt w wywoaniu
metody zdalnej tworzy jego kopi, ktra jest przesyana. W celu przesania kopii
obiektu lokalnego konieczna jest jego konwersja do takiej formy zbioru bajtw, aby
bya odtwarzalna po stronie serwera aplikacji. Konieczne jest zatem, dostpne w
Javie, zastosowanie mechanizmu serializacji (klasy obiektw musz implementowa
interfejs Serializable). Prawie wszystkie obiekty mog by w ten sposb podlega
konwersji, z wyjtkiem tych, ktre maj charakter lokalny (np. odnosz si do plikw
lokalnych). Przesyanie obiektw poprzez ich kopie wykonywane jest rwnie dla tych
obiektw po stronie serwera aplikacji (zdalnej), ktre nie implementuj interfejsu
Remote, czyli s obiektami lokalnymi serwera lecz nie stanowi w wietle RMI
obiektw zdalnych. Podsumowujc, moliwe s nastpujce formy przekazywania
argumentw i wynikw dziaania metod:
- przez warto: w komunikacji dwustronnej poprzez warto przekazywane s
proste typy danych jak: int, boolean, iitp),
- przez referencj zdaln: w komunikacji klient -> serwer przekazywana jest zdalna
referencja zdalnego obiektu,
- przez kopi: - czyli rwnie przez warto w komunikacji dwustronnej poprzez
kopie przekazywane s obiekty inne ni zdalne (tzn. te dziedziczce po interfejsie
Remote).
8-34
8-35
8-37
8-38
Uzyskiwana w ten sposb zdalna referencja (stub) wskazuje na obiekt klasy Object,
ktrego typ trzeba rzutowa na typ danego interfejsu obiektu zdalnego:
Srednia s = (Srednia) o;
lub razem:
Srednia s = (Srednia) Naming.lookup(rmi://medvis.eti.pg.gda.pl/srednia).
Uzyskujc w ten sposb referencj obiektu zdalnego mona wywoa zdefiniowan
metod zdaln. Przykadowy program klienta przedstawiono poniej:
Przykad 8.19:
//SredniaKlient.java:
import java.rmi.*;
import java.util.*;
public class SredniaKlient{
public static void main(String args[]){
if (System.getSecurityManager()==null)
System.setSecurityManager(new RMISecurityManager());
try{
Random r = new Random();
int n = r.nextInt(50);
Srednia s = (Srednia) Naming.lookup("rmi://medvis.eti.pg.gda.pl/srednia");
Double d = s.policzSrednia(n);
System.out.println("Srednia z kolejnych"+ n+" wartoci wynosi: "+d);
}catch (Exception e){
System.out.println("Wystpi wyjtek: "+ e);
}
}
}// koniec public class SredniaKlient
8-39
8-40
access
denied
8-41