Vous êtes sur la page 1sur 18

N342 Remote Server

Invocation

Search
Modified: 12/01/2006 06:16:29

Overview
Time Client/Server
o
Exercise 1 - Time Client/Server
Distributed Processing
o
Exercise 2 - Sort Client/Server
Multiple SortServerImpl
o
Exercise 3 - Multiple Sort Client
Threading
o
Exercise 4 - Threaded Multiple Sort Client

Overview - RMI is the infrastructure for a program on one computer to


execute methods (procedures) located on another over a network.
Methods may pass/receive parameters and return results, the calling
program must normally wait until the called method completes
execution as it would with a standard method call. Using RMI to build a
service (i.e. the UPS shipping rate service) has advantages in that
communication between the client and server consists of
passing objects as parameters rather than text in a message. All the
expressiveness of objects can be utilized (there are some restrictions
such as complete thread state can't be passed) so that a linked list could
be passed as a parameter rather than converted into text, transmitted,
and converted back into a linked list on the receiving end. One
disadvantage is that RMI only works with Java because other languages
and computers represent data differently, a large problem for
developing general services.
Because RMI is Java-based its use is limited as a general solution for
building Web or Internet services. An open solution for distributed
services being developed is .NET by Microsoft. Where Java passes data
(method parameters and results) as Java obejcts, .NET converts data
and passes as XML. We have examined ways in which programs can
explicitly generate and parse XML, .NET performs this conversion
between language representations and XML transparently, allowing one
language to invoke methods of another (e.g. Java could call a C++
method, any parameters would be converted from Java-to-XML-to-C++
representation. Another key feature of .NET is that calls can be made to
modules (methods/functions/subroutines) on the same or other
computers with no change to the caller or calling program, offering the
potential for a truly networked language.

site

po

Time Client/Server
We will implement a simple Time service client/server using Java RMI.
Clients obtain the current time by invoking a method getTime( ) on the
remote time server. There are three Java files necessary to implement a
client/server relation using RMI:
1. Interface - TimeServerInf.java - Interface definition of all server
methods that can be called by the remote client. The server
implementation must define String getTime( )method.
2. Server - TimeServerImpl.java - Implements the methods that are
defined in the interface (i.e. String getTime( ) ).
3. Client - TimeClient.java - Client calls to remote methods on the
server, (i.e. getTime( ) ).
// TimeServerInf.java interface definition
import java.rmi.*;
public interface TimeServerInf extends Remote {
public String getTime() throws RemoteException;
}
// TimeServerImpl.java
import java.rmi.*;
import java.rmi.server.*;
public class TimeServerImpl extends UnicastRemoteObject implements
TimeServerInf {
public TimeServerImpl() throws RemoteException { super(); }
// implementation for TimeServerInf interface method, return the
current date/time as String
public String getTime() {
return new java.util.Date().toString();
}
public static void main( String args[] ) throws Exception {
System.err.println( "Initializing server: please wait." );
// create server object and bind TimeServerImpl object to the
rmiregistry on default port 1099

Naming.rebind( "//localhost/Time", new TimeServerImpl()

);
}

System.err.println("The Time Server is up and running." );

}
// TimeClient.java
import java.rmi.*;
public class TimeClient {
public static void main( String args[] ) throws Exception {
// lookup TimeServerInf remote object in rmiregistry on port 1099
of local host
TimeServerInf ts = (TimeServerInf) Naming.lookup(
"//localhost/Time" );
// get time from server
System.out.println(ts.getTime());
}

TimeClient Output
The time is: Tue Jun 19 11:30:36 EDT 2001
RMI software components - The RMI software components include
the infrastructure to suppport a programming model where apparent
communication is directly between the client and server as illustrated at
left below.

Apparent
Client/Server
Communication

Actual Client/Server Communication

In fact, there are four main communicating software components in a


minimal RMI client/server system, their relationship is illustrated in the
diagram at right above.

Client - Looks up the server object using Naming.lookup(


"//localhost/Time" ) and invokes remote server methods (e.g.
getTime( ) ).
Stub Class - The RMI compiler rmic used to generate a stub class
from the server implementation used by the client to invoke RMI
server methods. The stub class handles client networking between
server when a remote method is invoked by the
client. TimeServerImpl_Stub.class is generated by rmic to provide
networking services to TimeServerImpl.
RMI registry - Registers the TimeServerImpl server
as //localhost/Time when Naming.rebind( "//localhost/Time", new
TimeServerImpl() ) is invoked by the server program.
Thermiregistry is a server normally running on port 1099 that
directly communicates with the stub class and the server. Client
communication invoking a server method would pass through the
stub class, which would connect to the rmiregistry server, which
would pass the method invocation to the TimeServerImpl.
Returning results would propagate in the reverse direction fom the
server to the client.
Server - The TimeServerImpl server registers itself
with rmiregistry as //localhost/Time, when the RMI
method Naming.rebind( "//localhost/Time", new TimeServerImpl()
) is invoked.

This model hides nearly all the details of communication between


networked hosts. Chief issues handled are:

Networking - Protocol for client/server communication. The


RMI stub class handles client-side communication,
the registry handles server-side. Because RMI handles networking
details, the client invokes a server method much as it would a
client method.
Data communication - Client side communications (based on
TCP) are handled by the Stub class while server side
communications are handled by the RMI Registry. Because RMI is
Java specific, only Java classes can be represented and objects
transported between the client/server.
Data marshalling - Java classes used in RMI must
support serialization, which basically means that data of an object
can be written to a file, network connection or other streamable

device. Data marshalling is essentially translating the internal Java


representation of an object into a serialized version that can be
transported over a network. Certain object attributes such as
memory addresses or thread state cannot be serialized in general.
The following differs from the original by (see bold parts
of TimeServerImpl.java and TimeClient.java below):
1. The TimeClient can call a TimeServerImpl on any machine
address.
2. The TimeServerImpl returns the machine name with the time.
Time Client/Server
// TimeServerInf.java interface definition
import java.rmi.*;
public interface TimeServerInf extends Remote {
public String getTime() throws RemoteException;
}
// TimeServerImpl.java
import java.rmi.*;
import java.rmi.server.*;
public class TimeServerImpl extends UnicastRemoteObject implements
TimeServerInf {
public TimeServerImpl() throws RemoteException { super(); }
// implementation for TimeServerInf interface method
public String getTime() {
try { return java.net.InetAddress.getLocalHost() + " " + new
java.util.Date().toString(); }
catch(Exception e) { return "Failed"; }
}
public static void main( String args[] ) throws Exception {
System.err.println( "Initializing server: please wait." );
// create server object and bind TimeServerImpl object to the
rmiregistry
Naming.rebind( "//localhost/Time", new TimeServerImpl() );

}
}
//

System.err.println("The Time Server is up and running." );

TimeClient.java

import java.rmi.*;
public class TimeClient {
public static void main( String args[] ) throws Exception {
String host = "localhost";
if (args.length > 0) host = args[0];
// lookup TimeServerInf remote object in rmiregistry
TimeServerInf ts = (TimeServerInf) Naming.lookup( "//" +
host + "/Time" );
// get time from server
System.out.println(ts.getTime());
}

}
Output:
ray-laptop/127.0.0.1 Tue Jun 19 11:02:59 EDT 2001

Exercise 1 - Time Client/Server


1. Copy and paste the three Java programs into the same directory
using the names
1. TimeServerInf.java
2. TimeServerImpl.java
3. TimeClient.java.
2. Copy and paste the commands below left. Due to startup race
conditions, the TimeClient may start before the TimeServerImpl is
fully running, you will need to enter the last line again by hand if
the TimeClient fails.
3. Find out a class mate's machine IP or name that is running
the TimeServerImpl and get its time. To get the time from lf111b0.ius.edu by:
java TimeClient lf111-b0.ius.edu
Commands to Compile and Execute Time RMI Client/Server
path=C:\JDK1.2.2\BIN;%path%
Define path to Java

set
classpath=%classpath%;.;C:\JDK1.2.2\lib\class
es.zip
javac *.java
rmic -v1.2 TimeServerImpl
start rmiregistry
start java TimeServerImpl
java TimeClient

components
Define classpath to
Java components
Compile all Java
programs.
Generate a Java 2
TimeServerImpl_Stub.c
lass used by client to
invoke RMI server
methods.
Start the RMI registry
used to bind server
objects to host and port
number (normally port
1099).
Start the server and
bind to host and port
number.
Execute client invoking
getTime method on
server.

Distributed Processing
RMI is a general remote computing model that can support virtually any
client/server application. The TimeClient/TimeServerImpl was an
example of RMI as a server, where the server provided time a s a
service to the client. As an example of distributed processing, sorting on
a server will be examined where multiple servers each sort a part of an
array and the client merges the parts into a whole sorted array. First a
simpler example of a single server sorting a client array.
The key software elements are the same as before:
1. Interface - SortServerInf.java - Interface definition of all server
methods that can be called by the remote client. The server
implementation must define method:
int[] sort(int data[])
2. Server - SortServerImpl.java - Implements the methods that are
defined in the interface (i.e. int[] sort(int data[]) ).
3. Client - SortClient.java - Client calls to remote methods on the
server, (i.e. int[] sort(int data[]) ).

Sort Client/Server
// SortServerInf.java interface definition
import java.rmi.*;
public interface SortServerInf extends Remote {
public int[] sort( int data[] ) throws RemoteException;
}
// SortServerImpl.java
import java.rmi.*;
import java.rmi.server.*;
public class SortServerImpl extends UnicastRemoteObject implements
SortServerInf {
public SortServerImpl() throws RemoteException { super(); }
// implementation for SortServerInf interface method
public int[] sort( int data[] ) {
int n = data.length;
int temp;
for (int pass = 0; pass < n-1; pass++)
for (int pair=0; pair < n-pass-1; pair++)
if( data[pair] < data[pair+1]) {
temp = data[pair];
data[pair] = data[pair+1];
data[pair+1] = temp;
}
return data;
}
public static void main( String args[] ) throws Exception {
System.err.println( "Initializing server: please wait." );
String number = "";
if (args.length > 0) number = args[0];
// create server object and bind SortServerImpl object to the
rmiregistry
Naming.rebind( "//localhost/Sort" + number, new
SortServerImpl() );

System.err.println("The Sort Server " + number + " is up and


running." );
}
}
// SortClient.java
import java.rmi.*;
public class SortClient {
public static void main( String args[] ) throws Exception {
int unsorted[] = {93, 81, 95, 74};
int sorted[];
String host = "localhost";
if (args.length > 0) host = args[0];
// lookup SortServerInf remote object in rmiregistry
SortServerInf ss = (SortServerInf) Naming.lookup( "//" + host +
"/Sort" );
// Sort on server
sorted = ss.sort(unsorted);

System.out.println("Unsorted Sorted");
for (int i=0; i<unsorted.length; i++)
System.out.println(unsorted[i] + "

" + sorted[i]);

}
Output:
Unsorted Sorted
93
95
81
93
95
81
74
74

Exercise 2 - Sort Client/Server


1. Copy and paste the three Java programs below into the same
directory using the names
1. SortServerInf.java

2. SortServerImpl.java
3. SortClient.java.
2. Copy and paste the commands below left. Due to startup race
conditions, the SortClient may start before the SortServerImpl is
fully running, you will need to enter the last line again by hand if
the SortClient fails.
3. Find out a class mate's machine IP or name that is running
the SortServerImpl and have it. To sort from lf111-b0.ius.edu by:
o java SortClient lf111-b0.ius.edu
4. What changes are needed to run multiple servers:
0. Changes to the SortServerInf.java?
1. Changes to the SortServerImpl.java?
2. Changes to the SortClient.java?
3. Changes to the command below?
Running the Sort Client/Server
path=C:\JDK1.2.2\BIN;%path%
Define path to Java
set
components
classpath=%classpath%;.;C:\JDK1.2.2\lib\class Define classpath to
es.zip
Java components
javac *.java
Compile all Java
rmic -v1.2 SortServerImpl
programs.
start rmiregistry
Generate a Java 2
start java SortServerImpl
SortServerImpl_Stub.cl
java SortClient
ass used by client to
invoke RMI server
methods.
Start the RMI registry
used to bind server
objects to host and
port number (normally
port 1099).
Start the server and
bind to host and port
number.
Execute client invoking
sort method on server.

Multiple SortServerImpl
A more realistic distributed processing example would be to have
multiple SortServerImpl each sorting an array that is returned to the
client and merged to produce a fully sorted array.

The SortServerImpl difference is in how it is started in


that multiple servers are executed, each with a
different name registered with the rmiregistry. There will be
a//localhost/Sort1 and //localhost/Sort2 servers.
The SortClient difference is that it invokes the sort method on two
servers, Sort1 and Sort2, to sort two different arrays. The arrays
are sorted by the client and merged.
The SortServerInf does not change.

The apparent object transfer between the client and the two server

is:

//

Sort Client with Multiple Servers


MultiSortClient.java

import java.rmi.*;
public class MultiSortClient {
public static void main( String args[] ) throws Exception {
int
int
int
int

unsorted1[] = {93, 81, 95, 74};


unsorted2[] = {93, 81, 95, 74};
sorted1[], sorted2[];
sorted[];

String host1 = "localhost", host2 = "localhost";


if (args.length == 2) { host1 = args[0]; host2 = args[1]; }
// lookup SortServerInf remote object in rmiregistry
SortServerInf ss1 = (SortServerInf) Naming.lookup( "//" +
host1 + "/Sort1" );
SortServerInf ss2 = (SortServerInf) Naming.lookup( "//" +
host2 + "/Sort2" );
// Sort on server
sorted1 = ss1.sort(unsorted1);
sorted2 = ss2.sort(unsorted2);
sorted = new MultiSortClient().merge(sorted1, sorted2);

System.out.println("Sorted");
for (int i=0; i<sorted.length; i++)
System.out.println(sorted[i]);
}
private int[] merge(int s1[], int s2[]) {
int merged[] = new int[s1.length+s2.length];
int i1=0, i2=0;

for (int i=0; i<merged.length; i++)


if (i1 == s1.length) merged[i] = s2[i2++];
else if (i2 == s2.length) merged[i] = s1[i1++];
else if (s1[i1] > s2[i2]) merged[i]=s1[i1++];
else merged[i] = s2[i2++];
return merged;

}
Output:
Sorted
95
95
93
93
81
81
74
74

Exercise 3 - Multiple Sort Client


1. Copy and paste the Java program above into the same directory
as before using the name:
1. MultiSortClient.java.
2. Copy and paste the commands below left. Due to startup race
conditions, the MultiSortClient may start before
the SortServerImpl is fully running, you will need to enter the last
line again by hand if the MultiSortClient fails.
3. Find out a class mate's machine IP or name that is running
the SortServerImpl. Sort from lf111-b0.ius.edu and lf111b1.ius.edu by:
o java MultiSortClient lf111-b0.ius.edu lf111-b1.ius.edu
4. Identify changes needed to run multiple servers:

0.
1.
2.
3.

Changes
Changes
Changes
Changes

to
to
to
to

the
the
the
the

SortServerInf.java?
SortServerImpl.java?
MultiSortClient.java?
command below?

Running the Sort Client and Multiple Servers


path=C:\JDK1.2.2\BIN;%path%
Define path to Java
set
components
classpath=%classpath%;.;C:\JDK1.2.2\lib\class Define classpath to
es.zip
Java components
javac *.java
Compile all Java
rmic -v1.2 SortServerImpl
programs.
start rmiregistry
Generate a Java 2
start java SortServerImpl 1
SortServerImpl_Stub.cl
start java SortServerImpl 2
ass used by client to
java MultiSortClient
invoke RMI server
methods.
Start the RMI registry
used to bind server
objects to host and
port number (normally
port 1099).
Start the server and
bind to
//localhost/Sort1 and
port number.
Start the server and
bind to
//localhost/Sort2 and
port number.
Execute client invoking
sort method on server.

Threading
The multiple sort client above has one serious weakness, although the
sorting is distributed amoung several sort servers no advantage is
gained in reduced overall time. This can be understood by an
examination of the client and recalling that remote method invocations
behave as a regular method invocation, the caller is blocked until the
method returns. In the following the second invocation is not made until
the first is completed:
sorted1 = ss1.sort(unsorted1);
// Wait till completed

sorted2 = ss2.sort(unsorted2);
// Wait till completed
The time the client and server SS1 and SS2 execute can be illustrated
as:
where each
executes sequentially. Ideally both sorts would occur simultaneously,
This can be achieved by making each server sort invocation in a
seperate thread on the client and waiting for each server to finished
before merging the sorted arrays. The following implements a threaded
client that is in other aspects the same as the previous example. The
key changes are:
1. an additional class SortThread
1. that runs a thread for calling a sort server,
2. can be checked for sort completion,
3. returns the sorted array.
2. the client
1. creates and runs one thread for each server,
2. while a server is sorting waits,
3. when all servers are finished sorting, retrieves the sorted
array.
With the use of threads the sort servers can be started and monitored
for completion. The execution of the client and sort servers SS1 and SS2
is illustrated at right. Each can execute in parallel so that the time to
complete is, in theory at least, reduced. Because of networking and RMI
overhead, reduced execution time
may not be a fact.
// TMultiSortClient.java
import java.rmi.*;
class SortThread extends Thread {
int unsorted[], sorted[];
SortServerInf ss;
String name;
boolean sorting;
public SortThread(SortServerInf ss,
int unsorted[], String name) {
this.unsorted = unsorted;
this.ss = ss;
this.name = name;
sorting = true;

}
public int[] getSorted() {
return sorted;
}
public void run() {
System.out.println("Started
thread " + name);
try {
sorted =
ss.sort(unsorted);
} catch(Exception e) {}
System.out.println("Finished
thread " + name);
sorting = false;
}
public boolean sorting() {
return sorting;
}
}
public class TMultiSortClient {
public static void main( String args[]
) throws Exception {
int unsorted1[] = {93, 81, 95,
74};
74};

int unsorted2[] = {93, 81, 95,


int sorted1[], sorted2[];
int sorted[];
SortThread thread1, thread2;

String host1 = "localhost", host2


= "localhost";
if (args.length == 2) { host1 =
args[0]; host2 = args[1]; }
// lookup SortServerInf remote
object in rmiregistry
SortServerInf ss1 =
(SortServerInf) Naming.lookup( "//" +
host1 + "/Sort1" );

SortServerInf ss2 =
(SortServerInf) Naming.lookup( "//" +
host2 + "/Sort2" );
// Start sort threads
thread1 = new
SortThread(ss1, unsorted1,
"Sort1");
thread2 = new
SortThread(ss2, unsorted2,
"Sort2");
thread1.start();
thread2.start();
// Wait while either thread is
sorting
while(thread1.sorting() ||
thread2.sorting())
System.out.println("Sorting");;
sorted = new
TMultiSortClient().merge(thread1.getS
orted(), thread2.getSorted());
System.out.println("Sorted");
for (int i=0; i<sorted.length;
i++)

System.out.println(sorted[i

]);
}
private int[] merge(int s1[], int
s2[]) {
int merged[] = new
int[s1.length+s2.length];
int i1=0, i2=0;
for (int i=0; i<merged.length;
i++)

if (i1 == s1.length)
merged[i] = s2[i2++];
else if (i2 == s2.length)
merged[i] = s1[i1++];

else if (s1[i1] > s2[i2])


merged[i]=s1[i1++];
else merged[i] =
s2[i2++];
return merged;
}
}
Output
Sorting
Started thread Sort2
Started thread Sort1
Sorting
Sorting
Finished thread Sort2
Finished thread Sort1
Sorting
Sorted
95
95
93
93
81
81
74
74
Running the Threaded Sort Client and Multiple Servers
path=C:\JDK1.2.2\BIN;%path%
Define path to Java
set
components
classpath=%classpath%;.;C:\JDK1.2.2\lib\class Define classpath to
es.zip
Java components
javac *.java
Compile all Java
rmic -v1.2 SortServerImpl
programs.
start rmiregistry
Generate a Java 2
start java SortServerImpl 1
SortServerImpl_Stub.cl
start java SortServerImpl 2
ass used by client to
java TMultiSortClient
invoke RMI server
methods.
Start the RMI registry
used to bind server
objects to host and
port number (normally
port 1099).

Start the server and


bind to
//localhost/Sort1 and
port number.
Start the server and
bind to
//localhost/Sort2 and
port number.
Execute client invoking
sort method on all
servers.

Exercise 4 - Threaded Multiple Sort Client


1. Copy and paste the Java program above into the same directory
as before using the name:
1. TMultiSortClient.java.
2. Copy and paste the commands below left. Due to startup race
conditions, the TMultiSortClient may start before
the SortServerImpl is fully running, you will need to enter the last
line again by hand if the TMultiSortClient fails.
3. Find out a class mate's machine IP or name that is running
the SortServerImpl. Sort from lf111-b0.ius.edu and lf111b1.ius.edu by:
o java TMultiSortClient lf111-b0.ius.edu lf111-b1.ius.edu
4. Run the TMultiSortClient several times and notice the difference in
the output.
5. Modify TMultiSortClient.java and the commands to handle three
servers.

Vous aimerez peut-être aussi