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