Download - Distribution Transparency in C# Klaus-Peter Löhr Institut für Informatik Freie Universität Berlin
Distribution Transparency in C#
Klaus-Peter Löhr
Institut für InformatikFreie Universität Berlin
www.inf.fu-berlin.de
Distribution Transparency (a.k.a. Network Transparency)
= access transparency +
location transparency +
. . . . .
DT as a property of a programming language and its supporting environment:
a language system is dt if any program written in the language
looks like a „regular“ (centralized, non-distributed) program,
can be executed in a distributed fashion,
behaves no different if executed in a distributed instead of a centralized fashion.
„DT is a boon!“ (the purists)
„DT is a red herring!“ (Waldo et al.)
DT is more a quantitative than a qualitative property.
A good amount of DT can be useful for many applications.
The two extremes
No DT: - explicit message passing instead of remote invocation, or
- syntactical access transparency, but differring semantics for remote invocation;
- explicit handling of remote hosts and processes, of channel and ports;
- program management: explicit stub generation (if any), program configuration, code placement, .....
Perfect DT governed by
- compilation/linking options,
- platform switches,
- configuration files.
Basics of .NET Remotingusing C# notation
Terminology:
Xremote
invocation
x
client server serverclientserver
Remote Invocation:
object x can be invoked remotely if these requirements are met:
its class X inherits from System.MarshalByRefObject:
class X : MarshalByRefObject{ .....
public void op(string message){ Console.WriteLine(message);}
}
a server port number has explicitly been registered by the server;
the client has somehow got a remote reference to the object x.
client server
ChannelServices.RegisterChannel( new TcpServerChannel(null, 4711);
X rem = ... ..... // create and publish x// get hold of x
x.op("hello on server"); // local test
..... Console.WriteLine("Hit ENTER for shutting down server:");
rem.op("hello Console.ReadLine(); from client"); // remote call
.....
Remote Access to fields and properties:
value = rem.age; works fine, and so does
rem.age = value; !
Also holds for properties of class X :
public int age{ set ...
get ...}
Publishing a local object for sharing:
X x = new X(...); // local creation
RemotingServices.Marshal(x,"publicX");// publishing
Client gets hold of the object named publicX in this way:
X rem = (X)Activator.GetObject( typeof(X), "tcp://host:4711/publicX");
Remote Creation of private objects:
Server must be prepared:
RemotingConfiguration.RegisterActivatedServiceType(typeof(X));
Console.WriteLine("Hit ENTER for shutting down server:");
Console.ReadLine();
Client has several options, among them:
object[] attr = {new UrlAttribute("tcp://host:4711")};object[] args = {...}; // constructor argumentsobject o = Activator.CreateInstance(typeof(X),args,attr);X rem = (X)o;
Program Management: compile X,compile server,
compile client,
install compiled server+X on host,
install compiled client+X,
start server
hello on server
start client
hello from client
then
Java RMI vs. .NET Remoting
Object and its proxy must share Transparent proxy, can be cast to Xa common interface
RemoteExceptions must be no such requirementhandled or declared
Publishing requires extra naming no such requirementservice (rmiregistry)
Advance proxy/skeleton generation no such requirement (generation (rmic X) on the fly from class metadata)
not supported Remote creation
Parameter Passing
Parameter modes:
int op( int a, // call-by-value argument out int b, // call-by-result argument
ref int c) // call-by-reference argumentresult
void inc(bool cond, ref int x, ref int y){ if(cond) x++; else y++; }
? Effect of x.inc(cond, a[i], a[k]);
! If x happens to be remote and cond && i == k then a is not modified !
BUT CAUTION with remote calls: ref works call-by-value-result :
! MORE CAUTION if actual parameter is object reference:
if object is remotely invokable: remote reference to object is handed out
if object is serializable: reference to local copy is handed out
if neither: exception is raised
class RemoteStack : MarshalByRefObject{ int[] stack = new int[100];
.....public int[] dump() { return stack; } // arrays are serializable!.....
}
RemoteStack
0 1 2 . .a = rem.dump();
a
rem
a[0] = 8;
x = rem.bot();
0 1 2 . .
x == 0
RemoteStack
0 1 2 . .
x == 8
client server
Remember:
in a distributed setting, you may not know
whether or not an object is a MarshalByRefObject
and if it is,
whether or not it is indeed remote from the client -
unpredictable invocation semantics !
interface IStack { ... }class RemStack : MarshalByRefObject, IStack { ... }class Stack : IStack { ... }
..... void op(IStack stack) { ..... }
Remote Event Handling
Language supports observer pattern:
class Observed{public delegate void ringHandler(.,.);public event ringHandler ring;
// signal event:... ring(.,.); ...
}
class Observer{ ... Observed x; ... // subscribe to event: x.ring += new Observed. ringHandler(beep); ...public void beep(.,.) {... // do beep}}
class Observed: Marshal..{public delegate void ringHandler(.,.);public event ringHandler ring;
// signal event:... ring(.,.); ...
}
class Observer: Marshal..{ ... Observed x; ... // get remote x // subscribe to event: x.ring += new Observed. ringHandler(beep); ...public void beep(.,.) {... // do beep}}
Distributed version works fine, too:
observer machine observed machine
static ??
Subscription causes Observer class to be reinstantiated at observed site
Observed machine starts beeping !
Assessment
C#/CLR is richer than Java/JVM - curse or boon?
.NET Remoting is more distribution-transparent than Java RMI,
BUT does not avoid all of Java‘s transparency deficiencies
AND introduces new ones along with the new features
Other important facets of .NET Remoting:
Achieve more transparency through configuration files (XML)
Http channels (as opposed to Tcp channels) support XML- coded remote invocation (SOAP) Web Services
... more
Reference
Web Resources:
msdn.microsoft.com/library : search for .NET Remotingwww.dotnetremoting.cc
Book:
Ingo Rammer: Advanced .NET Remoting. APress 2002
These slides:
www.inf.fu-berlin.de/~lohr/slides/csrem.ppt
Code samples follow on slides below
// file server.cs: creates private RemText objects for clients on demand
// compile with csc server.cs, producing server// compile with csc /t:library server.cs, producing server.dll
using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Tcp;
public class RemText : MarshalByRefObject{
public static void Main() { ChannelServices.RegisterChannel(new TcpServerChannel(4711)); RemotingConfiguration.RegisterActivatedServiceType(typeof(RemText)); Console.WriteLine("Hit ENTER to stop server."); Console.ReadLine(); }
string text;
public RemText(string init) {Console.WriteLine("Text object created.");text = init; }
public void replace(string s) {Console.WriteLine("replacing " + text + " with " + s);text = s;return; }
public string remove() {if(text==null) throw new Exception("nothing to remove");string result = text; text = null;Console.WriteLine("removing " + result);return result; }
}
// file client.cs: remote creation and invocation of a RemText object
// compile with csc /r:server.dll client.cs, producing client
// test: start server in separate window,// start client
using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Tcp;
public class Test{
public static void Main(){
Console.WriteLine("Create remote text object ...");object[] attr = {new UrlAttribute("tcp://localhost:4711")};object[] args = {"initial text"}; // constructor argument
RemText text = (RemText)Activator.CreateInstance(typeof(RemText), args, attr);
Console.WriteLine("Invoke object ...");Console.WriteLine(text.remove()); // should write "initial text"Console.WriteLine("Hit ENTER for another try:");Console.ReadLine();Console.WriteLine(text.remove()); // should raise exception
}}
// File od.cs: Observed code
// compile with csc od.cs, producing od// compile with csc /t:library od.cs, producing od.dll
using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Tcp;
public class Observed : MarshalByRefObject{
public static void Main(){
ChannelServices.RegisterChannel(new TcpServerChannel(null, 4711));
Observed observed = new Observed(); Console.WriteLine("Register observed ...");RemotingServices.Marshal(observed,"observed object");
for(;;) {Console.Write("Hit ENTER to signal event:"); Console.ReadLine(); observed.ring(null,null);
}}
public delegate void ringHandler(object source, EventArgs args);// mandatory signature for event handlers
public event ringHandler ring;}
// File or.cs: Observer code
// compile with csc /r:od.dll or.cs, producing or
// test: start od in separate window,// start or,// hit ENTER in od window
using System;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation;using System.Runtime.Remoting.Channels;using System.Runtime.Remoting.Channels.Tcp;
public class Observer : MarshalByRefObject{
public static void Main(){
ChannelServices.RegisterChannel(new TcpServerChannel(null, 4712));
Console.WriteLine("Get observed object ...");Observed observed = (Observed)Activator.GetObject(
typeof(Observed), "tcp://localhost:4711/observed object");
Observer observer = new Observer(observed);Console.ReadLine(); // wait for events
}public Observer(Observed observed){
Console.WriteLine("Subscribe to observed object ...");observed.ring += new Observed.ringHandler(beep);
}public void beep(object o, EventArgs a){ Console.WriteLine("beep"); }
}