260 likes | 474 Views
Distribution Transparency in C#. Klaus-Peter Löhr Institut für Informatik Freie Universität Berlin www.inf.fu-berlin.de. Distribution Transparency (a.k.a. Network Transparency) = access transparency + location transparency + .
E N D
Distribution Transparency in C# Klaus-Peter Löhr Institut für Informatik Freie 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 isdt 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.
Outline Basics of .NET Remoting Parameter Passing Remote Event Handling Assessment
Basics of .NET Remoting using C# notation Terminology: client server server client server x remote invocation X
Remote Invocation: objectxcan be invoked remotely if these requirements are met: its classXinherits 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 ... }
Publishinga local object for sharing: X x = new X(...); // local creation RemotingServices.Marshal(x,"publicX"); // publishing Client gets hold of the object namedpublicXin this way: X rem = (X)Activator.GetObject( typeof(X), "tcp://host:4711/publicX");
Remote Creationof 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 arguments object 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, then start client start server hello on server hello from client
Java RMI vs. .NET Remoting Object and its proxy must share Transparent proxy, can be cast to X a common interface RemoteExceptions must be no such requirement handled or declared Publishing requires extra naming no such requirement service (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 argument result BUT CAUTION with remote calls: ref works call-by-value-result : 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 andcond && i == kthen a is not modified !
! 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! ..... }
client server RemoteStack rem RemoteStack a = rem.dump(); 0 1 2 . . 0 1 2 . . a 0 1 2 . . a[0] = 8; x = rem.bot(); x == 0 x == 8
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 Observer { ... Observed x; ... // subscribe to event: x.ring += new Observed. ringHandler(beep); ... public void beep(.,.) {... // do beep} } class Observed { public delegate void ringHandler(.,.); public event ringHandler ring; // signal event: ... ring(.,.); ... }
Distributed version works fine, too: observer machine observed machine class Observer: Marshal.. { ... Observed x; ... // get remote 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(.,.); ... } Observed machine starts beeping ! static?? Subscription causes Observer class to be reinstantiated at observed site
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 Remoting www.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"); } }