460 likes | 632 Views
Remote Method Invocation (RMI). Client-Server Communication. Sockets Remote Procedure Calls Remote Method Invocation (Java). Sockets. A socket is defined as an endpoint for communication . Concatenation of IP address and port
E N D
Client-Server Communication • Sockets • Remote Procedure Calls • Remote Method Invocation (Java)
Sockets • A socket is defined as an endpoint for communication. • Concatenation of IP address and port • The socket 161.25.19.8:1625 refers to port 1625 on host 161.25.19.8 • Communication consists between a pair of sockets. • Considered a low-level form of communication between distributed processes. • Sockets allow only an unstructured stream of bytes to be exchanged. It is the responsibility of the client or server application to impose a structure on the data.
Remote Procedure Calls • Remote procedure call (RPC) abstracts procedure calls between processes on networked systems. • Stub – client-side proxy for the actual procedure on the server. Server has a similar stub as well. • The client-side stub locates the server and marshals the parameters. • The server-side stub receives this message, unpacks the marshaled parameters, and performs the procedure on the server. • External data representation (XDR) I.e most-significant (big-endian), least-significant(little-endian)
Remote Method Invocation • Remote Method Invocation (RMI) is a Java mechanism similar to RPCs. • RMI allows a Java program on one machine to invoke a method on a remote object.
Remote Method Invocation • RMI and RPC differs in two ways: • RPCs support procedural programming whereby only remote procedures or functions may be called. RMI is object based: It supports invocation of methods on remote objects. • The parameters to remote procedures are ordinary data structures in RPC; with RMI it is possible to pass objects as parameters to remote methods. • If the marshaled parameters are local (non remote) objects, they are passed by copy using a technique known as object serialization. • Object serialization allowed the state of an object to be written toa byte stream.
Introduction to RMI • Remote Method Invocation (RMI) • Allows remote method calls • Objects in different programs can communicate • Method calls appear same as those in same program • Based on Remote Procedure Calls (RPC) • Developed in 1980's • Allows procedural program (like C) to call function on another computer • Performs networking and marshalling of data (packaging arguments and return values) • Not compatible with objects • Interface Definition Language required - describe functions • RMI is Java's implementation of RPC
Introduction to RMI • RMI • Register method as remotely accessible • Client can look up method and receive a reference • Use reference to call method • Syntax same as a normal method call • Marshalling of data • Can transfer objects as well • Class ObjectOutputStream converts Serializable object into stream of bytes • Transmit across network • Class ObjectInputStream reconstructs object • No Interface Definition Language needed • Use Java's own interface
Case Study: Creating a Distributed System with RMI • RMI example • Downloads weather information from National Weather Service website http://iwin.nws.noaa.gov/iwin/us/traveler.html • Note: Format of website changed several times, if example does not work do the appropriate modifications. • Store information on a server • Request information through remote method calls
Case Study: Creating a Distributed System with RMI • Four major steps • Define remote interface • Describes client/server communication • Define server application to implement remote interface • Same name as remote interface, ends with Impl • Define client application that uses remote interface reference • Interacts with server implementation • Compile and execute server and client
Defining the Remote Interface • First step • Define remote interface that describes remote methods • Client calls remote methods, server implements them • To create a remote interface • Define interface that extends interface Remote (java.rmi) • Tagging interface - no methods to define • An object of a class that implements interface Remote directly or indirectly is a remote object and can be accesses from any JVM. • Each method in Remote interface must throw RemoteException • Potential network errors
Defining the Remote Interface • Interface TemperatureServer • Extends Remote • Describes method getWeatherInfo
1 // Fig. 20.1: TemperatureServer.java 2 // TemperatureServer interface definition Interface Remote in java.rmi 3import java.rmi.*; 4 5 public interface TemperatureServer extends Remote { Methods in Remote interface (is a relationship) must be able to throw a RemoteException. 6 public WeatherInfo[] getWeatherInfo() 7 throws RemoteException; 8 } 1. import 1.1 extendsRemote 2. getWeatherInfo 2.1 throwsRemoteException
Implementing the Remote Interface • Define TemperatureServerImpl • Implements Remote interface TemperatureServer • Client interacts with TemperatureServerImpl object • Uses array of WeatherInfo objects to store data • Copy sent to client when calls getWeatherInfo
37 URL url = new URL( 38 "http://iwin.nws.noaa.gov/iwin/us/traveler.html" ); 18 public class TemperatureServerImpl extends UnicastRemoteObject 19 implements TemperatureServer { 22 public TemperatureServerImpl() throws RemoteException Implementing the Remote Interface • UnicastRemoteObject • Provides functionality for remote objects • Constructor exports object so it can receive remote calls • Wait for client on anonymous port number • Subclass constructors must throw RemoteExceptions • URL object • Contains URL for Traveler's Forecast web page • Throws MalformedURLException
40 BufferedReader in = 41 new BufferedReader( 42 new InputStreamReader( url.openStream() ) ); Implementing the Remote Interface • Open connection to file specified by URL • Method openStream (class URL) • Opens network connection using Http protocol • If successful, InputStream object returned (else IOException) • InputStreamReader • Translates bytes to Unicode characters • BufferedReader • Buffers characters • Method readLine • Returns one line as a String
44 String separator = "</PRE><HR> <BR><PRE>"; 47 while ( !in.readLine().startsWith( separator ) ) 48 ; // do nothing 51 String s1 = 52 "CITY WEA HI/LO WEA HI/LO"; 66 inputLine = in.readLine(); // get first city's info Implementing the Remote Interface • Sentinel String to find relevant part of HTML code • readLine until sentinel found • A string used as column head • Second "WEA HI/LO" is for next day, we do not use • Locate column head and get first city's info
70 WeatherInfo w = new WeatherInfo( 71 inputLine.substring( 0, 16 ), 72 inputLine.substring( 16, 22 ), 73 inputLine.substring( 23, 29 ) ); 75 cityVector.addElement( w ); // add to Vector 84 weatherInformation[ i ] = 85 ( WeatherInfo ) cityVector.elementAt( i ); 88 in.close(); // close connection to NWS server Implementing the Remote Interface • WeatherInfo objects • City name, temperature, description of weather • Method substring to extract data from line • Store all WeatherInfo objects in a Vector • Store data in WeatherInfo array • elementAt returns Object (must be cast) • Close connection
116 String serverObjectName = "//localhost/TempServer"; Implementing the Remote Interface • Name of server object • Used by clients to connect • //host:port/remoteObjectName • host - computer running registry for remote objects • Where remote object executes • port - port number of registry on host (1099 default) • remoteObjectName - client uses to locate object • Registry managed by rmiregistry (located at host and port) • Remote objects register with it, clients use it to locate service • localhost (same computer) • Same as IP 127.0.0.1
112 TemperatureServerImpl temp = 113 new TemperatureServerImpl(); 116 String serverObjectName = "//localhost/TempServer"; 117 Naming.rebind( serverObjectName, temp ); Implementing the Remote Interface • static method rebind (class Naming) • Binds object to rmiregistry • Named //localhost/TempServer • Name used by client • rebind replaces any previous objects with same name • Method bind does not
1 // Fig. 20.1: TemperatureServer.java 2 // TemperatureServer interface definition 3 import java.rmi.*; 4 5 public interface TemperatureServer extends Remote { 6 public WeatherInfo[] getWeatherInfo() Allows objects to be exported. 7 throws RemoteException; 8 } 9 TemperatureServer interface. 10 // Fig. 20.2: TemperatureServerImpl.java Superclass constructor exports objects, and this constructor must be able to throw RemoteException. 11 // TemperatureServerImpl definition 12 import java.rmi.*; 13 import java.rmi.server.*; 14 import java.util.*; 15 import java.io.*; 16 import java.net.*; 17 18public class TemperatureServerImpl extends UnicastRemoteObject 19 implements TemperatureServer { 20 private WeatherInfo weatherInformation[]; 21 22 public TemperatureServerImpl() throws RemoteException 23 { 24 super(); 25 updateWeatherConditions(); 26 } 27 1. Interface ------------------ 1. extends UnicastRemote Object, implements TemperatureServer 1.1 Constructor
34 "Updating weather information..." ); 35 36 // Traveler's Forecast Web Page URL of web site (URL object). 37 URL url = new URL( 38 "http://iwin.nws.noaa.gov/iwin/us/traveler.html" ); 39 40 BufferedReader in = 41 new BufferedReader( Open connection to file. InputStreamReader formats it to Unicode characters, and BufferedReader buffers the characters. 42 new InputStreamReader( url.openStream() ) ); 43 readLine until separator found. 44 String separator = "</PRE><HR> <BR><PRE>"; 45 46 // locate first horizontal line on Web page 47 while ( !in.readLine().startsWith( separator ) ) 48 ; // do nothing 49 50 // s1 is the day format and s2 is the night format 51 String s1 = 52 "CITY WEA HI/LO WEA HI/LO"; 53 String s2 = 54 "CITY WEA LO/HI WEA LO/HI"; 55 String inputLine = ""; 56 28 // get weather information from NWS 29 private void updateWeatherConditions() 30 throws RemoteException 31 { 32 try { 33 System.err.println( 2. updateWeather Conditions 2.1 URL 2.2 BufferedReader 2.3 readLine
67 68 while ( !inputLine.equals( "" ) ) { Create WeatherInfo object, add data (substring), add to Vector. Loop until blank line reached. 69 // create WeatherInfo object for city 70 WeatherInfo w = new WeatherInfo( 71 inputLine.substring( 0, 16 ), 72 inputLine.substring( 16, 22 ), 73 inputLine.substring( 23, 29 ) ); 74 Create WeatherInfo array, cast Vector elements. 75 cityVector.addElement( w ); // add to Vector 76 inputLine = in.readLine(); // get next city's info 77 } 78 79 // create array to return to client 80 weatherInformation = 81 new WeatherInfo[ cityVector.size() ]; 82 83 for ( int i = 0; i < weatherInformation.length; i++ ) 84 weatherInformation[ i ] = 85 ( WeatherInfo ) cityVector.elementAt( i ); 86 57 // locate header that begins weather information 58 do { 59 inputLine = in.readLine(); 60 } while ( !inputLine.equals( s1 ) && 61 !inputLine.equals( s2 ) ); 62 63 64 Vector cityVector = new Vector(); 65 66 inputLine = in.readLine(); // get first city's info 2.4 Locate header 2.5 Loop 2.5.1 WeatherInfo 2.5.2 readLine 2.6 WeatherInfo array
100 // implementation for TemperatureServer interface method 101 public WeatherInfo[] getWeatherInfo() 102 { 103 return weatherInformation; 104 } Return the WeatherInfo array. 105 106 public static void main( String args[] ) throws Exception 107 { 108 System.err.println( 109 "Initializing server: please wait." ); 110 111 // create server object 112 TemperatureServerImpl temp = 113 new TemperatureServerImpl(); 114 87 System.err.println( "Finished Processing Data." ); 88 in.close(); // close connection to NWS server 89 } 90 catch( java.net.ConnectException ce ) { 91 System.err.println( "Connection failed." ); 92 System.exit( 1 ); 93 } 94 catch( Exception e ) { 95 e.printStackTrace(); 96 System.exit( 1 ); 97 } 98 } 99 2.7 close 3. getWeatherInfo 4. main 4.1 temp
Name of server object. rebind binds object to rmiregistry. 115 // bind TemperatureServerImpl object to the rmiregistry 116 String serverObjectName = "//localhost/TempServer"; 117 Naming.rebind( serverObjectName, temp ); 118 System.err.println( 119 "The Temperature Server is up and running." ); 120 } 121 } 4.2 serverObjectName 4.3 rebind
1 / Fig. 20.3: WeatherInfo.java This allows objects to be passed as a stream of bytes. 2 // WeatherInfo class definition 3 import java.rmi.*; 4 import java.io.Serializable; 5 6public class WeatherInfo implements Serializable { 7 private String cityName; 8 private String temperature; 9 private String description; 10 11 public WeatherInfo( String city, String desc, String temp ) 12 { 13 cityName = city; 14 temperature = temp; 15 description = desc; 16 } 17 18 public String getCityName() { return cityName; } 19 20 public String getTemperature() { return temperature; } 21 22 public String getDescription() { return description; } 23 } 1. Class WeatherInfo implements Serializable 1. Instance variables 1.1 Constructor 2. Get methods
Define the client • Next step • Client code to get weather info from TemperatureServerImpl • Calls getWeatherInfo through RMI • Graphically display weather info • Class WeatherItem (extends JLabel) stores info about each city • Display name, High/low, and image (depending on conditions)
34 WeatherInfo weatherInfo[] = mytemp.getWeatherInfo(); 22 private void getRemoteTemp( String ip ) 26 String serverObjectName = "//" + ip + "/TempServer"; 30 TemperatureServer mytemp = ( TemperatureServer ) 31 Naming.lookup( serverObjectName ); Define the client • Can specify IP address at command line (more later) • static method lookup (class Naming) • Returns reference to Remote object • Cast to TemperatureServer • Reference may be used as normal • Only difference that copy of array returned
68 public static void main( String args[] ) 69 { 70 TemperatureClient gt = null; 40 JPanel p = new JPanel(); 74 if ( args.length == 0 ) 75 gt = new TemperatureClient( "localhost" ); 76 else 77 gt = new TemperatureClient( args[ 0 ] ); 50 for ( int i = 0; i < w.length; i++ ) { 51 w[ i ] = new WeatherItem( weatherInfo[ i ] ); 52 p.add( w[ i ] ); 53 } Define the client • Add WeatherItems • Initialize with WeatherInfo • main • Passes command line argument (ip) to constructor • localhost default
18 static { 19 backgroundImage = new ImageIcon( "images/back.jpg" ); 20 weatherImages = 21 new ImageIcon[ weatherImageNames.length ]; 22 23 for ( int i = 0; i < weatherImageNames.length; ++i ) 24 weatherImages[ i ] = new ImageIcon( 25 "images/" + weatherImageNames[ i ] + ".jpg" ); 26 } Define the client • Class WeatherItem • extends JLabel • static initializer block • For complex initialization of static variables • backgroundImage - ImageIcon, has background • weatherImages - ImageIcon array, holds weather images
35 weatherInfo = w; 38 for ( int i = 0; i < weatherConditions.length; ++i ) 39 if ( weatherConditions[ i ].equals( 40 weatherInfo.getDescription().trim() ) ) { 41 weather = weatherImages[ i ]; 32 public WeatherItem( WeatherInfo w ) Define the client • Array of descriptions and matching array of images • weatherConditions and weatherImages • Tests WeatherInfo object, loads proper image
1 // Fig. 20.4: TemperatureClient.java 2 // TemperatureClient definition 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 import java.rmi.*; Use ip specified at command line. 7 Lookup remote object in registry. Returns Remote reference, cast to proper type. 8 public class TemperatureClient extends JFrame 9 { 10 public TemperatureClient( String ip ) 11 { 12 super( "RMI TemperatureClient..." ); 13 getRemoteTemp( ip ); 14 15 setSize( 625, 567 ); 16 setResizable( false ); 17 show(); 18 } 19 20 // obtain weather information from TemperatureServerImpl 21 // remote object 22 private void getRemoteTemp( String ip ) 23 { 24 try { 25 // name of remote server object bound to rmi registry 26 String serverObjectName = "//" + ip + "/TempServer"; 27 28 // lookup TemperatureServerImpl remote object 29 // in rmiregistry 30 TemperatureServer mytemp = ( TemperatureServer ) 31 Naming.lookup( serverObjectName ); 1. import 1.1 Constructor 2. getRemoteTemp 2.1 serverObjectName 2.2 Naming.lookup
34 WeatherInfo weatherInfo[] = mytemp.getWeatherInfo(); 35 WeatherItem w[] = Call like regular method. 36 new WeatherItem[ weatherInfo.length ]; 37 ImageIcon headerImage = 38 new ImageIcon( "images/header.jpg" ); 39 40 JPanel p = new JPanel(); 41 42 // determine number of rows for the GridLayout; 43 // add 3 to accommodate the two header JLabels 44 // and balance the columns 45 p.setLayout( 46 new GridLayout( ( w.length + 3 ) / 2, 2 ) ); 47 p.add( new JLabel( headerImage ) ); // header 1 48 p.add( new JLabel( headerImage ) ); // header 2 49 50 for ( int i = 0; i < w.length; i++ ) { 51 w[ i ] = new WeatherItem( weatherInfo[ i ] ); 52 p.add( w[ i ] ); 53 } 54 55 getContentPane().add( new JScrollPane( p ), 56 BorderLayout.CENTER ); 57 } 58 catch ( java.rmi.ConnectException ce ) { 59 System.err.println( "Connection to server failed. " + 60 "Server may be temporarily unavailable." ); 61 } 32 33 // get weather information from server 2.3 getWeatherInfo 2.4 GUI 2.4.1 WeatherItem
67 68 public static void main( String args[] ) 69 { 70 TemperatureClient gt = null; 71 72 // if no sever IP address or host name specified, args[ 0 ] is the first argument, which should be the IP address. 73 // use "localhost"; otherwise use specified host 74 if ( args.length == 0 ) 75 gt = new TemperatureClient( "localhost" ); 76 else 77 gt = new TemperatureClient( args[ 0 ] ); 78 79 gt.addWindowListener( 80 new WindowAdapter() { 81 public void windowClosing( WindowEvent e ) 82 { 83 System.exit( 0 ); 84 } 85 } 86 ); 87 } 88 } 62 catch ( Exception e ) { 63 e.printStackTrace(); 64 System.exit( 1 ); 65 } 66 } 3. main 3.1 args[ 0 ]
1 // Fig. 20.5: WeatherItem.java 2 // WeatherItem definition 3 import java.awt.*; 4 import javax.swing.*; 5 6 public class WeatherItem extends JLabel { 7 private static ImageIcon weatherImages[], backgroundImage; 8 private final static String weatherConditions[] = 9 { "SUNNY", "PTCLDY", "CLOUDY", "MOCLDY", "TSTRMS", 10 "RAIN", "SNOW", "VRYHOT", "FAIR", "RNSNOW", 11 "SHWRS", "WINDY", "NOINFO", "MISG" }; Use names in weatherImageNames array to load ImageIcons. 12 private final static String weatherImageNames[] = 13 { "sunny", "pcloudy", "mcloudy", "mcloudy", "rain", 14 "rain", "snow", "vryhot", "fair", "rnsnow", 15 "showers", "windy", "noinfo", "noinfo" }; 16 17 // static initializer block to load weather images 18 static { 19 backgroundImage = new ImageIcon( "images/back.jpg" ); 20 weatherImages = 21 new ImageIcon[ weatherImageNames.length ]; 22 23 for ( int i = 0; i < weatherImageNames.length; ++i ) 24 weatherImages[ i ] = new ImageIcon( 25 "images/" + weatherImageNames[ i ] + ".jpg" ); 26 } 27 28 // instance variables 29 private ImageIcon weather; 30 private WeatherInfo weatherInfo; 1. Class WeatherItem 1.1 static variables 1.2 Initializer block 1.3 Load ImageIcons
34 weather = null; 35 weatherInfo = w; 36 37 // locate image for city's weather condition 38 for ( int i = 0; i < weatherConditions.length; ++i ) Loop though weatherConditions and compare to getDescription. 39 if ( weatherConditions[ i ].equals( 40 weatherInfo.getDescription().trim() ) ) { 41 weather = weatherImages[ i ]; 42 break; 43 } Attach background to WeatherItem. 44 45 // pick the "no info" image if either there is no 46 // weather info or no image for the current 47 // weather condition 48 if ( weather == null ) { 49 weather = weatherImages[ weatherImages.length - 1 ]; 50 System.err.println( "No info for: " + 51 weatherInfo.getDescription() ); 52 } 53 } 54 55 public void paintComponent( Graphics g ) 56 { 57 super.paintComponent( g ); 58 backgroundImage.paintIcon( this, g, 0, 0 ); 59 31 32 public WeatherItem( WeatherInfo w ) 33 { 2. Constructor 2.1 Compare conditions 3. paintComponent 3.1 paintIcon
67 } 68 69 // make WeatherItem's preferred size the width and height of 70 // the background image Draw city name, high/low, and attach weather image to WeatherItem. 71 public Dimension getPreferredSize() 72 { 73 return new Dimension( backgroundImage.getIconWidth(), 74 backgroundImage.getIconHeight() ); 75 } 76 } 60 Font f = new Font( "SansSerif", Font.BOLD, 12 ); 61 g.setFont( f ); 62 g.setColor( Color.white ); 63 g.drawString( weatherInfo.getCityName(), 10, 19 ); 64 g.drawString( weatherInfo.getTemperature(), 130, 19 ); 65 66 weather.paintIcon( this, g, 253, 1 ); 3.2 drawString 3.3 paintIcon
Compile and Execute the Server and the Client • Build and execute application • All pieces in place • Compile classes with javac • Remote server class (TemperatureServerImpl) compiled with rmic compiler • Makes a stub class - allows client to access remote methods and server to provide its services • Gets remote method calls, passes to RMI system, which performs networking • rmic TemperatureServerImpl
Compile and Execute the Server and the Client • Start rmiregistry • Type rmiregistry at command window • No text in response
Compile and Execute the Server and the Client • Must bind remote server object • Run TemperatureServerImpl application java TemperatureServerImpl • Superclass UnicastRemoteObject • Constructor exports remote object • main binds object to rmiregistry • rmiregistry provides host and port number to clients
Compile and Execute the Server and the Client • Execute TemperatureClient • java TemperatureClient • If server on different machine, specify IP on command line java TemperatureClient 192.168.150.4 • Result on next slide