Java – programowanie w sieci 

java.net



RMI

Programowanie sieciowe OSI WARSTWA APLIKACJI (7) WARSTWA PREZENTACJI(6)

DoD

Java

Warstwa aplikacji (HTTP)

Warstwa aplikacji (np. HTTP)

Transport (gniazdka)

Transport (TCP, UDP)

Sieć (datagramy, adresy IP)

Sieć (IP)

Dostęp do sieci

Połączenie (Sterowniki urządzeń)

WARSTWA SESJI (5) WARSTWA TRANSPORTU (4)

WARSTWA SIECIOWA (3)

WARSTWA ŁĄCZA DANYCH (2) WARSTWA FIZYCZNA (1)

java.net Klasy/interfejsy do adresowania IP ● ustanawiania połączeń TCP ● wysyłania i otrzymywania datagramów via UDP ● lokalizacji i identyfikacji zasobów sieciowych ● identyfikacji ● autoryzacji ●

java.net -- adresowanie IP ●

Klasy do adresowania IP Ipv4 (32b) i Ipv6 (128b)

public class MyDNS { public static void main(String[] args) throws Exception {

}

}

java.net.InetAddress a = java.net.InetAddress.getByName(args[0]); System.out.println(a);

java.net -- adresowanie gniazdek ●

Klasy do adresowania gniazdek SocketAddress (abstrakcyjna) InetSocketAddress

SocketAddress= new InetSocketAddress( “localhost”, 80 ); SocketAddress= new InetSocketAddress( “volt”, 8080 );

Gniazdka (1) Port Serwer

Żądanie połączenia

Klient

Port Serwer

Klient Port

Gniazdko (socket) to punkt końcowy połączenia pomiędzy dwoma programami działającymi w sieci. Gniazdko jest przypięte do określonego portu.

Gniazdka (2)

Strona klienta Socket socket = null; PrintWriter out = null; BufferedReader in = null; try { socket = new Socket( args[0], Integer.parseInt( args[1] )); out = new PrintWriter(socket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( socket.getInputStream())); } catch (UnknownHostException e) { System.err.println("Don't know about host: " + args[0] ); System.exit(1); } catch (IOException e) { System.err.println("Couldn't get I/O for " + "the connection to: " + args[0] + " port " + args[1] ); System.exit(1); } catch ( NumberFormatException e ) { System.err.println( "Port no. must be” “ an integer number - got " + args[1] ); System.exit(1); }

Strona serwera ServerSocket serverSocket = null; try { serverSocket = new ServerSocket( Integer.parseInt(args[0])); } catch (IOException e) { System.err.println("Could not listen on port: "+args[0]); System.exit(1); } catch(NumberFormatException e ) { System.err.println( "Port number!” ); System.exit(1); } Socket clientSocket = null; try { clientSocket = serverSocket.accept(); } catch (IOException e) { System.err.println("Accept failed."); System.exit(1); } PrintWriter out = new PrintWriter( clientSocket.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader( clientSocket.getInputStream()));

Ćwiczenie: połączenie TCP ●

Serwer http://www.iem.pw.edu.pl/~jstar/MyServer.java



Klient http://www.iem.pw.edu.pl/~jstar/MyClient.java

Datagramy UDP (1) ●







Tworzymy gniazdko Tworzymy pakiet Wysyłamy Możemy odebrać odpowiedź

Datagramy UDP (2) // Tworzymy gniazdko DatagramSocket socket = new DatagramSocket(); // Szykujemy pakiet byte[] buf = new byte[256]; InetAddress address = InetAddress.getByName(args[0]); DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445); // Wysyłamy go socket.send(packet); // Odbieramy odpowiedź packet = new DatagramPacket(buf, buf.length); socket.receive(packet); // Wyciągamy z niej dane String received = new String(packet.getData());

Datagramy UDP (3) socket = new DatagramSocket(4445); ... public void run() { while (cośTam) { try { byte[] buf = new byte[256]; // Przyjmij żądanie DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet); // Adres nadawcy InetAddress address = packet.getAddress(); int port = packet.getPort(); // Odpowiedz buf= response( buf ); packet = new DatagramPacket(buf, buf.length, address, port); socket.send(packet);

Ćwiczenie: datagramy UDP ●

Serwer http://www.iem.pw.edu.pl/~jstar/quotes.txt http://www.iem.pw.edu.pl/~jstar/QuteServer.java http://www.iem.pw.edu.pl/~jstar/QuoteServerThread.java



Klient http://www.iem.pw.edu.pl/~jstar/QuoteClient.java

Dostęp do zasobów sieci ● ● ● ● ● ● ●

URI URL URLClassLoader URLConnection URLStreamHandler HttpURLConnection JarURLConnection

Połączenie URL (1)

Połączenie URL (2) import java.net.*; import java.io.*; public class URLConnectionReader { public static void main(String[] args) throws Exception { URL goo = new URL("http://www.google.pl/"); URLConnection gc = goo.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( gc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } }

Można też od razu tak: import java.net.*; import java.io.*; public class URLRead { public static void main(String[] args) throws Exception { URL url = new URL( args[0] ); InputStreamReader in = new InputStreamReader( url.openStream()); String input= in.read(); System.out.println(input); in.close(); } }

URLe w Swingu import javax.swing.*; import javax.swing.event.*; import javax.swing.text.html.*; ... editorPane.addHyperlinkListener( new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { JEditorPane pane = (JEditorPane) e.getSource(); if (e instanceof .HTMLFrameHyperlinkEvent) { HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e; HTMLDocument doc = (HTMLDocument)pane.getDocument(); doc.processHTMLFrameHyperlinkEvent(evt); } else { try { pane.setPage(e.getURL()); } catch (Throwable t) { t.printStackTrace(); } } } } });

RMI (Remote Method Invocation): mechanizm wywoływania metod klas działających na innej maszynie wirtualnej.

Co to jest RMI RMI to API wspomagające tworzenie rozproszonych aplikacji obiektowych (Distributed Object Application) ● Aplikacja taka składa się zwykle z kilku (min. 2) programów, działających na różnych komputerach ● Najprostszy model to działający na jednym z komputerów program-klient, który wywołuje metody obiektów programu-serwera. ● RMI zapewnia mechanizm komunikacji klienta z serwerem ●

Co to jest RMI RMI

RMI

Internet

Wymagania ● ● ●

Lokalizacja zdalnych obiektów Komunikacja ze zdalnymi obiektami Przekazywanie kodu pośredniego Rejestr RMI

Klient

HTTP RMI

Serwer WWW

HTTP

HTTP

RMI

Serwer

Serwer WWW

Mechanizm komunikacji

Klient

Namiastka

Odbiornik

Serwer

Namiastka i Obiorca Odbiorca: Namiastka: ● odtwarza parametry ● tworzy po stronie klienta blok danych zawierający: ● lokalizuje obiekt – opis wywoływanej ● wywołuje metodę metody ● pobiera wynik (wyjątek) – identyfikator zdalnego ● serializuje go obiektu ● wysyła dane do – parametry namiastki (serializowane) ● wysyła dane do serwera ● odbiera i rozpakowuje wynik

Klient (przykładowy) import java.rmi.Naming; import java.rmi.RMISecurityManager; public class ShowQuote { public static void main(String args[]) throws Exception { // Bywa jeszcze SecurityManager

}

}

String url= "rmi://localhost:1313/Quoter"; Quoter quoter = (Quoter)Naming.lookup( url ); System.out.println(quoter.getQuote());

Interfejs zdalny import java.rmi.Remote; import java.rmi.RemoteException; public interface Quoter extends Remote {

}

public abstract String getQuote() throws RemoteException;

Implementacja (zdalnego interfejsu Quoter) import java.rmi.*; import java.rmi.server.*; public class RMIQuoter extends UnicastRemoteObject implements Quoter { public RMIQuoter() throws RemoteException {} public String getQuote(){ return "Na razie nic mądrego"; } }

Serwer import java.rmi.Naming; public class RMIServer { public static void main(String args[]) throws Exception { RMIQuoter rmiquoter = new RMIQuoter(); Naming.bind( "Quoter", rmiquoter); System.out.println("Quoter ready."); } }

Wdrożenie Rejestr volt

Serwer

Klient

Quoter.class RMIQuoter.class RMIQuoter_Stub.class RMIServer.class

Serwer WWW

client.policy Quoter.class ShowQuote.class

max Quoter.class RMIQuoter_Stub.class

grant { permission java.net.SocketPermission "*:1024-65355", "connect"; permission java.net.SocketPermission "*:80", "connect"; };

Uruchomienie Maszyna serwera: $ rmiregistry & $ java -Djava.rmi.server.codebase=http:/max/~jstar/rmi_down/ RMIServer &

Klient: $ java -Djava.security.policy=client.policy ShowQuote volt

Serwer aktywowany ●





● ●

RMI pozwala tworzyć tanie środowiska obliczeniowe o dużej mocy Tworzenie i rejestracja obiektów zanim jakiś klient zechce z nich skorzystać może być nieefektywne Serwery aktywowane są generowane na żądanie klienta Ze strony klienta wszystko wygląda tak samo Po stronie maszyny-serwera działa program aktywujący, który tworzy serwery na żądanie

Serwer aktywowany import java.rmi.*; import java.rmi.activation.*; public class ActRMIQuoter extends Activatable implements Quoter { String quote; public String getQuote()throws RemoteException { return "Na razie nic mÄdrego"; } public ActRMIQuoter( ActivationID id, MarshalledObject data ) throws RemoteException { super( id, 0 ); quote= (String) data.get(); } }

Aktywator import ... public class RMIActivator { public static void main(String args[]) throws Exception { Properties props= new Properties(); props.put("java.security.policy", new File("server.policy").getCanonicalPath() ); ActivationGroupDesc grdesc= new ActivationGroupDesc( props, null ); ActivationGroupID agid= ActivationGroup.getSystem().registerGroup( grdesc ); String classURL= args.length == 0 ? new File( "." ).getCanonicalFile().toURL().toString() : args[0]; System.out.println( "Class URL=" + classURL ); ActivationDesc adsc= new ActivationDesc( agid, "ActRMIQuoter" classURL, new MarshalledObject(“Cytat”) ); Quoter q= (Quoter)Activatable.register( adsc );

}

}

Naming.bind( "Quoter", q); System.out.println("Quoter ready. Exiting");

Wdrożenie aktywatora Klient

Rejestr Serwer

volt

ActRMIQuoter.class ActRMIQuoter_Stub.class RMIActivator.class rmid.policy Quoter.class server.policy

max

client.policy Quoter.class ShowQuote.class

grant { permission com.sun.rmi.rmid.ExecPermission "${java.home}${/}bin${/}java"; permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*"; };

Serwer WWW

Quoter.class ActRMIQuoter_Stub.class

grant { permission java.security.AllPermission "", ""; };

Uruchomienie Maszyna serwera: $ rmiregistry \ -J-Djava.rmi.server.codebase=http:/max/~jstar/rmi_down/ & $ rmid -J-Djava.security.policy=rmid.policy & $ java RMIActivator http://max/~jstar/rmi_down/

Klient: $ java -Djava.security.policy=client.policy ShowQuote volt

Ćwiczenia: 1. Pobrać: http://www.iem.pw.edu.pl/~jstar/rmiclient.tgz, skompilować i uruchomić klienta Poeksperymentować z plikiem policy 2. Pobrać: http://www.iem.pw.edu.pl/~jstar/rmiserver.tgz, skompilować i uruchomić server 3. Napisać i wdrożyć własną aplikację: klient wysyła do serwera napis (np. imię), serwer odpowiada “Witaj