Java programowanie w sieci java.net RMI
Programowanie sieciowe OSI WARSTWA APLIKACJI (7) WARSTWA PREZENTACJI(6) WARSTWA SESJI (5) WARSTWA TRANSPORTU (4) DoD Warstwa aplikacji (HTTP) Transport (gniazdka) Java Warstwa aplikacji (np. HTTP) Transport (TCP, UDP) WARSTWA SIECIOWA (3) Sieć (datagramy, adresy IP) Sieć (IP) WARSTWA ŁĄCZA DANYCH (2) WARSTWA FIZYCZNA (1) Dostęp do sieci Połączenie (Sterowniki urządzeń)
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) Serwer Serwer Port Port Port Żądanie połączenia Klient Klient 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 RMI Rejestr HTTP Klient HTTP RMI RMI Serwer WWW Serwer WWW HTTP Serwer
Mechanizm komunikacji Klient Namiastka Odbiornik Serwer
Namiastka i Obiorca Namiastka: tworzy po stronie klienta blok danych zawierający: opis wywoływanej metody identyfikator zdalnego obiektu parametry (serializowane) wysyła dane do serwera odbiera i rozpakowuje wynik Odbiorca: odtwarza parametry lokalizuje obiekt wywołuje metodę pobiera wynik (wyjątek) serializuje go wysyła dane do namiastki
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 Serwer volt Klient Quoter.class RMIQuoter.class RMIQuoter_Stub.class RMIServer.class client.policy Quoter.class ShowQuote.class Serwer WWW 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 max Rejestr Serwer ActRMIQuoter.class ActRMIQuoter_Stub.class RMIActivator.class rmid.policy Quoter.class server.policy Serwer WWW Quoter.class ActRMIQuoter_Stub.class volt Klient 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=*"; ; 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 <imię>