distribution transparency in c# klaus-peter löhr institut für informatik freie universität berlin

25
Distribution Transparency in C# Klaus-Peter Löhr Institut für Informatik Freie Universität Berlin www.inf.fu-berlin.de

Upload: margaretmargaret-bond

Post on 17-Dec-2015

220 views

Category:

Documents


2 download

TRANSCRIPT

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.

Outline

Basics of .NET Remoting

Parameter Passing

Remote Event Handling

Assessment

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"); }

}