24
Remoting Architecture in .NET By Skpananghat Remoting Architecture in .NET .......................................................................................... 1 By Skpananghat .............................................................................................................. 1 Introduction ..................................................................................................................... 1 Remoting ......................................................................................................................... 2 AppDomains ................................................................................................................... 2 Marshalling ..................................................................................................................... 3 Marshal by reference: ................................................................................................. 3 Marshal by Value ........................................................................................................ 3 Serialization .................................................................................................................... 4 Remoting ........................................................................................................................ 4 Activation Types ............................................................................................................. 5 Server-activated types ................................................................................................. 5 Client-activated types.................................................................................................. 6 Lifetime & Lease ............................................................................................................ 6 Remoting Configuration ................................................................................................. 9 Configuration Files ..................................................................................................... 9 System.Runtime.Remoting. RemotingConfiguration class ...................................... 11 RemotingServices.RegisterWellKnownServiceType ............................................... 11 Remoting Architecture .................................................................................................. 12 Proxies: ..................................................................................................................... 13 Channels:................................................................................................................... 14 System.Runtime.Remoting. ChannelServices .......................................................... 15 Channel Sinks ........................................................................................................... 15 Formatters ................................................................................................................. 16 Dispatcher ................................................................................................................. 18 Declaring Methods "One-Way" .................................................................................... 20 The Call Context ........................................................................................................... 20 Remoting Services ........................................................................................................ 20 Known Common Error Messages ................................................................................. 21 System.Runtime.Remoting.TrackingServices .......................................................... 21 Asynchronous Remoting............................................................................................... 22 Calling Remote Methods Asynchronously ............................................................... 22 Call backs with Delegates ......................................................................................... 23 Introduction This is an in-depth, look at Remoting infrastructures in the Common Language Runtime and the .NET Framework. This study provides detailed information of the

Remoting Architecture in.Net

Embed Size (px)

Citation preview

Page 1: Remoting Architecture in.Net

Remoting Architecture in .NET

By Skpananghat

Remoting Architecture in .NET.......................................................................................... 1

By Skpananghat .............................................................................................................. 1

Introduction..................................................................................................................... 1

Remoting......................................................................................................................... 2

AppDomains ................................................................................................................... 2

Marshalling ..................................................................................................................... 3

Marshal by reference: ................................................................................................. 3

Marshal by Value........................................................................................................ 3

Serialization .................................................................................................................... 4

Remoting ........................................................................................................................ 4

Activation Types............................................................................................................. 5

Server-activated types ................................................................................................. 5

Client-activated types.................................................................................................. 6

Lifetime & Lease ............................................................................................................ 6

Remoting Configuration ................................................................................................. 9

Configuration Files ..................................................................................................... 9

System.Runtime.Remoting. RemotingConfiguration class ...................................... 11

RemotingServices.RegisterWellKnownServiceType ............................................... 11

Remoting Architecture.................................................................................................. 12

Proxies: ..................................................................................................................... 13

Channels:................................................................................................................... 14

System.Runtime.Remoting. ChannelServices .......................................................... 15

Channel Sinks ........................................................................................................... 15

Formatters ................................................................................................................. 16

Dispatcher ................................................................................................................. 18

Declaring Methods "One-Way" .................................................................................... 20

The Call Context ........................................................................................................... 20

Remoting Services ........................................................................................................ 20

Known Common Error Messages................................................................................. 21

System.Runtime.Remoting.TrackingServices .......................................................... 21

Asynchronous Remoting............................................................................................... 22

Calling Remote Methods Asynchronously ............................................................... 22

Call backs with Delegates......................................................................................... 23

Introduction

This is an in-depth, look at Remoting infrastructures in the Common Language Runtime

and the .NET Framework. This study provides detailed information of the

Page 2: Remoting Architecture in.Net

implementation of Remoting. I have givenonly a small description about each topic or

else it eat up very huge number of pages. And since i am not that much good in graphics,

I've grabbed the required images from other sources to depict some situation in this

document .

Remoting

NET remoting enables you to build widely distributed applications easily, whether the

application components are all on one computer or spread out across the entire world.

You can build client applications that use objects in other processes on the same

computer or on any other computer that is reachable over its network. In short NET

remoting provides an abstract approach to inter-process communication

Before getting deep into Remoting functionalities it would be good if I explain about

some other terms in .Net

AppDomains

An application domain is a partition in operating system process where one or more

applications reside or in other words Application domains are the isolated environments

where managed applications execute. .Net is having the concept of Appdomains just to

decrease the overhead of Win32 process isolation and memory handling tasks. You can

create as many Appdomains as you need and there will be a default "Appdomain". The

applications running under CLR (Managed environment) can be accessed using the

"Appdomain.CurrentDomain" property.

Thus Appdomains keeps the required assemblies separate with in the same Win32

process. Objects in the same application domain communicate directly. Objects in

different application domains communicate either by transporting copies of objects across

Page 3: Remoting Architecture in.Net

application domain boundaries, or by using a proxy to exchange messages. This is

accomplished by the process of marshalling and serialization

Marshalling

Marshalling and unmarshalling refers to packing and unpacking of parameters and return

values of a particular method call. There are 2 types of marshalling available in .Net.

Marshal by reference and Marshal by value. A simple synonym for marshalling would

be "packaging data for transfer".

Marshal by reference:

The first time an application in a remote application domain accesses a

MarshalByRefObject, a memory reference proxy is passed to the remote application.

A proxy is an object that exists and acts locally on behalf of a remote object. The proxy

looks like and accepts calls as if it where the "real" object.

The proxy exposes the same set of interfaces that original object exposes. However, the

proxy does not process the calls locally, but it holds the address or path to the actual

objects and thus sends them to the remote object it represents

Subsequent calls on the proxy are marshalled back to the object residing in the local

application domain. The same process is maintained regardless of whether the remote

application resides in a same physical machine, in same process or different physical

machine

This process of communicating between Appdomains is called Remoting, and we can

come to this point later on.

In order to make an object a MarshalByRef component you need to inherit it from

MarshalByRefObject class which internally handles the marshalling and lifetime

manipulation task of that object. MarshalByRefObject is the base class for objects that

communicate across application domain boundaries by exchanging messages using a

proxy.

Marshal by Value

Objects that do not inherit from MarshalByRefObject are implicitly marshal by value.

When a remote application references a marshal by value object, a copy of the object is

passed across application domain boundaries.

The basic difference is that a MarshalByRef component is not usable outside the

application domain where they were created where MarshalByvalue component is usable

just because it is having its state packed along.

Page 4: Remoting Architecture in.Net

Note: - Static variables and static methods cannot be proxied; instead it acts a marshal by

value sending a copy of the whole stuff to the client and will be executed in the clients

context.

Serialization

Serialization is the process of converting the state of an object into a form that can be

persisted or transported. The complement of serialization is deserialization, which

converts a stream into an object. Together, these processes allow data to be easily stored

and transferred.

The .NET Framework features two serializing technologies:

Binary serialization preserves type fidelity, which is useful for preserving the state of an

object between different invocations of an application. For example, you can share an

object between different applications by serializing it to the Clipboard. You can serialize

an object to a stream, to a disk, to memory, over the network, and so forth. Remoting uses

serialization to pass objects "by value" from one computer or application domain to

another.

XML serialization serializes only public properties and fields and does not preserve type

fidelity. This is useful when you want to provide or consume data without restricting the

application that uses the data. Because XML is an open standard, it is an attractive choice

for sharing data across the Web. SOAP is likewise an open standard, which makes it an

attractive choice.

Remoting ...

Now that you got some knowledge about "Appdomains" and all, we can continue with

remoting. As explained before, remoting provides an abstract approach to inter-process

communication. In either case if your remote objects reside in entirely different or same

physical machine, you need to host that application using some hosts which describes the

type, location and other simple metadata about that object

You must provide the following information to the remoting system to make your type

remotable:

• The type of activation required for your type.

• The complete metadata that describes your type.

• The channel registered to handle requests for your type.

• The URL that uniquely identifies the object of that type. In the case of server

activation, this means a Uniform Resource Identifier (URI) that is unique to that

Page 5: Remoting Architecture in.Net

type. In the case of client activation, a URL that is unique to that instance will be

assigned

You can provide this information either programmatically or through application

configuration files. So that you can change the configuration in future to point to any of

the other objects or machine without touching or recompiling the code.

The methods that will be called from the client are implemented in a remote object class.

In the figure below we can see an instance of this class as the Remote Object. Because

this remote object runs inside a process that is different from the client process – usually

also on a different system – the client can't call it directly. Instead the client uses a proxy.

For the client, the proxy looks like the real object with the same public methods. When

the methods of the proxy are called, messages will be created. These are serialized using

a formatter class, and are sent into a client channel. The client channel communicates

with the server part of the channel to transfer the message across the network. The server

channel uses a formatter to deserialize the message, so that the methods can be

dispatched to the remote object:

Activation – Remote objects can be activated using the new operator. Of course, there

are other ways to activate remote objects like Activator.GetObject(),

Activator.Createinstance() etc which will vary according to the activation type.

Activation Types

There are two types mainly Server activated types and client activated types

Server-activated types

Server-activated objects are objects whose lifetimes are directly controlled by the server.

The server application domain creates these objects only when the client makes a method

call on the object rather than when the client calls new or Activator.GetObject;

Page 6: Remoting Architecture in.Net

There are two activation modes (or WellKnownObjectMode values) for server-activated

objects: Singleton and SingleCall

Singleton types, as you know, never have more than one instance at any point of time. If

an instance exists, all client requests are serviced by that instance. If an instance does not

exist, the server creates an instance and all subsequent client requests will be serviced by

that instance.

SingleCall types always have one instance per client request. The next method

invocation will be serviced by a different server instance, even if the previous instance

has not expired in the system. SingleCall types do not participate in the lifetime lease

system.

To create an instance of a server-activated type, clients either configure their application

programmatically or use a configuration file and then pass the remote object's

configuration (Like type and object URI) in a call to Activator.GetObject.

Client-activated types

Client-activated objects are objects whose lifetimes are controlled by the calling

application domain, just as they would be if the object were local to the client.

Client-activated objects use lifetime leases to determine how long they should continue to

exist

Lifetime & Lease

Before telling about lease I would like to tell some thing about the garbage collection in

.net

The .NET Framework's garbage collector manages the allocation and release of memory

for your application. Each time you use the new operator (or

Activator.CreateInstance) to create an object, the runtime allocates memory for the

object from the managed heap. As long as address space is available in the managed

heap, the runtime continues to allocate space for new objects. However, memory is not

infinite. Eventually the garbage collector must perform a collection in order to free some

memory. The garbage collector's optimizing engine determines the best time to perform a

collection, based upon the allocations being made. When the garbage collector performs a

collection, it checks for objects in the managed heap that are no longer being used by the

application (the objects that have marked as unreachable in its object header) and

performs the necessary operations to reclaim their memory.

In our scenario, the client has reference to a proxy of the remote object in heap and there

should be a way by which the server can determine whether the reference to this server

object is still needed for the application. We achieve this particular function by

Page 7: Remoting Architecture in.Net

maintaining a leased lifetime for each server activated singleton and client activated

objects

In short leasing and sponsorship is the solution for managing the lifecycle of a remote

object in .NET. Each object has a lease that prevents the local garbage collector from

destroying it, and most distributed applications rely upon leasing. A sponsor is a third

party that the .NET Remoting Framework consults when a lease expires, giving that party

an opportunity to renew the lease

Whenever an MBR (Marshal-by-reference objects) object is remoted outside an

application domain, a lifetime lease is created for that object. Each application domain

contains a lease manager that is responsible for administering leases in its domain. A

server object can have many sponsors associated with its lease. The lease manager keeps

a list of all the sponsors. The lease manager periodically examines all leases for expired

lease times. If a lease has expired, the lease manager sends a request to its list of sponsors

for that object and queries whether any of them wants to renew the lease. If no sponsor

renews the lease, the lease manager removes the lease, the object is deleted, and its

memory is reclaimed by garbage collection. An object's lifetime, then, can be much

longer than its lifetime lease, if renewed more than once by a sponsor or by continually

being called by clients.

The Default lease time for an object is 5 Minutes, which is configured by overriding

MarshalByRefObject.InitializeLifetimeService and specifying our own

TimeSpan object as required

public override ILease InitializeLifetimeService ()

{

ILease lease = (ILease) base.InitializeLifetimeService ();

if (lease.CurrentState == LeaseState.Initial)

{

lease.InitialLeaseTime = TimeSpan.FromMinutes (1);

lease.SponsorshipTimeout = TimeSpan.FromMinutes (2);

lease.RenewOnCallTime = TimeSpan.FromSeconds (2);

}

return lease;

}

Page 8: Remoting Architecture in.Net

If the lease is about to expire, the .NET Remoting Framework will automatically extend

the lease on every call by the value set in the MarshalByRefObject. RenewOnCallTime

property. The default call time renewal is two minutes. The value of the current lease

time (the time the object has to live unless the lease is extended) is a product of the lease

time (the initial lease time for the first time) and renew on call time, according to the

formula shown in the following line of code:

Current lease time = MAX (lease time - expired time, RenewOnCallTime)

The RenewOnCallTime will have an effect only if it is greater than the lease time minus

the expired time. In that case, the expired time property is reset, and the lease time is set

to the RenewOnCallTime. The result is that even if an object is very busy, its lease time

does not grow in proportion to the amount of traffic it has. Even if the object has a

temporary spike in its load, its lease will expire after some quiet time.

If you know that a particular object will not be called for a longer period of time than the

default timeouts but you do not want to change the mechanism globally, you can create a

"sponsor" for that object and register it on the object's ILease interface that you can

obtain through the GetLifetimeService() method that every AppDomain bound,

MarshalByRefObject derived class and every contextful class inherits.

If an object's lease expires, the object is marked for garbage collection and all existing

remote references to this object become invalid.

The sponsor must implement the ISponsor interface, defined as:

public class ClientSponsor: MarshalByRefObject,ISponsor

{

public TimeSpan Renewal(ILease lease)

Page 9: Remoting Architecture in.Net

{

Debug.Assert(lease.CurrentState == LeaseState.Active);

//Renew lease by 5 minutes

return TimeSpan.FromMinutes(5);

}

}

After this we need to create the instance of the remotable object and register it with a

sponsor as follows

ISponsor sponsor = new ClientSponsor ();

MyClass obj = new MyClass();

// or MyClass obj = Activator.GetObject(typeof(MyClass), url)

//Register the sponsor

ILease lease = (ILease)RemotingServices.GetLifetimeService(obj);

lease.Register(sponsor);

The lease manager calls ISponsor's single method, Renewal, when the lease expires,

asking for new lease time

If the exception RemotingException: Object <URI> has been disconnected or does not

exist at the server occurs, this may be because of an expired lease time.

Remoting Configuration

Configuration Files

Both server and client channel can be configured programmatically or by using a

configuration file.

Using configuration files for remoting clients and servers has the advantage that the

channel and remote object can be configured without changing a single line of code and

without the need to recompile. Another advantage is that the remoting code we have to

write is very short.Specifying the options programmatically has the advantage that we

could get to the information during runtime. One way to implement this can be that the

client uses a directory service to locate a server that has registered its long running

objects there.

The server configuration file will look like this. We can call this file as SimpleServer.

exe.config.

<configuration>

Page 10: Remoting Architecture in.Net

<system.runtime.remoting>

<application name="SimpleServer">

<service>

<wellknown

mode="SingleCall"

type="Samples.MyRemoteObject, MyRemoteObject"

objectUri="MyRemoteObject" />

</service>

<channels>

<channel ref="tcp server" port="9000" />

</channels>

</application>

</system.runtime.remoting>

</configuration>

All the server has to do is read the configuration file and activate the channel. This can be

done with a single call to the static method RemotingConfiguration.Configure().

RemotingConfiguration.Configure() reads the configuration file

SimpleServer.exe.config to configure and activate the channel. The creation of the remote

object and communication with the client is done by the remoting infrastructure. We just

have to make sure that the process doesn't end. We do this with Console.ReadLine()

that will end the process when the user enters the return key:

// SimpleServer.cs

using System;

using System.Runtime.Remoting;

namespace Samples

{

class SimpleServer

{

static void Main(string[] args)

{

RemotingConfiguration.Configure("SimpleServer.exe.config");

Console.WriteLine("Press return to exit");

Console.ReadLine();

}

}

}

The client Channel would look like as follows. We can call this file as

SimpleClient.exe.config

<configuration>

<system.runtime.remoting>

<application name="SimpleClient">

<client url="tcp://localhost:9000/SimpleServer">

<wellknown

type="Samples.MyRemoteObject, MyRemoteObject"

url =

"tcp://localhost:9000/SimpleServer/MyRemoteObject"

/>

</client>

<channels>

Page 11: Remoting Architecture in.Net

<channel ref="tcp client" />

</channels>

</application>

</system.runtime.remoting>

</configuration>

As in the server, we can activate the client channel by calling

RemotingConfiguration.Configure(). Using configuration files we can simply use

new to create the remote object. Next we call the method Hello() of this object:

// SimpleClient.cs

using System;

using System.Runtime.Remoting;

namespace Samples

{

Public class SimpleClient

{

static void Main(string[] args)

{

RemotingConfiguration.Configure("SimpleClient.exe.config");

MyRemoteObject obj = new MyRemoteObject();

Console.WriteLine(obj.Hello());

}

}

}

System.Runtime.Remoting. RemotingConfiguration class

The RemotingConfiguration class provides facilities for Remoting configuration as well

as methods to register "well known objects" and client-activation objects

To expose (or publish) objects to clients, you need to register them with the

RemotingServices class using a "well-known" name. The RemotingServices itself bind

any registered object to the channels registered on the ChannelServices, so that each

object gets a "well-known" endpoint.

"Well-known" means that once you make that information available through your

program documentation, web-site, DISCO documents or UDDI, the clients can connect to

an object using a published and, hence, well-known name.

Objects can only be published using these well-known names and therefore the COM

concept of programmatic identifiers (ProgIDs) or class-identifiers (CLSIDs) is neither

supported nor required

RemotingServices.RegisterWellKnownServiceType

This is the way by which we register Singleton or Single Call objects programmatically

(without the help of configuration files). This is done with a call to

RegisterWellKnownServiceType(). That you register an object is, in fact, not entirely

Page 12: Remoting Architecture in.Net

accurate. You register the "type" (or better: class) of the object and the

RemotingConfiguration infrastructure will use the type information to either create a new

instance of that class for every call or to immediately create a new instance to be used as

a singleton object. In neither case you can pass arguments to the object at creation time –

just as in COM.

The example shown here illustrates the registration of a well-known object and the

resulting URI that a client can use to connect to the object's endpoint.

Registering a well-known object and making it available for remote clients doesn't take

more than three simple steps:

1. Create a new channel object instance, providing an IP port to listen on or some

other address information, if you have a custom channel.

2. Register the channel with the ChannelServices class.

3. Register the class of the object and the endpoint identifier, which must be unique

for your application. The last argument for the call indicates whether the object

shall be single call or singleton. Here, it's a SingleCall object.

The result from these registration steps is that your .NET application exposes an object

on the shown endpoint: "http://myserver:8080/MyEndpointURI".

Now your .NET application is independent of whether it is a service process, a Windows

Forms application or Console application is a full-blown HTTP server without using

Internet Information Server or another HTTP infrastructure. You can hit this address with

a standard web-browser appending "?WSDL" to the endpoint address and will see – the

WSDL service contract.

Remoting Architecture

The whole remoting architecture comprises of Messages, sinks, Proxies and configuration

objects.

Messages are objects that implement IMessage

Page 13: Remoting Architecture in.Net

Messages are the objects through which the information is transferred to another object.

From a programming standpoint, messages are objects that implement the IMessage

interface.

IMessage: The IMessage interface is a very simple dictionary of key/value pairs. The

message dictionary may contain any number of entries, each individually keyed by a

string. The values that are held in the message may be of any .NET object type. The

Remoting infrastructures task is to remote these dictionaries across Remoting boundaries

To make implementation of method calls consistent, .NET defines a few additional

message types that all implement the IMessage interface. The message types include

construction call messages and responses as well as method call messages and responses

If messages are being delivered synchronously, they represent a request that expect an

immediate response. If they are delivered asynchronously they represent a request that

expects a delayed response or no response at all.

Proxies:

As told earlier the proxy exposes the same set of interfaces that original object exposes.

However, the proxy does not process the calls locally, but it holds the address or path to

the actual objects and thus sends them to the remote object it represents

There are mainly two types of proxies used in the remoting context: The "RealProxy"

and the "Transparent proxy".

Transparent Proxies

A transparent proxy is a dynamically created block of code that exists in the client

application domain (or context) on behalf of the remote object and exposes all of its

features, including all fields, properties, events, delegates and methods. The transparent

proxy is an instance of the class System.Runtime.Remoting.Proxies.__

TransparentProxy. This class is internal to the mscorlib assembly, so we cannot derive

custom proxies from it

When you call a method of the transparent proxy, the proxy formats all of the arguments

and the method name into a message object and submits this through the real proxy's

Invoke() method to the remote object. Once the method returns, it decodes the message

elements and places them back on the local stack so that the calling code can pick them

up.

Page 14: Remoting Architecture in.Net

This diagram illustrates the dependencies between the real proxy and the transparent

proxy as well as the message sink and the channel. A client that uses an object across any

kind of a remoting boundary is actually using a transparent proxy for the object. The

transparent proxy provides the illusion that the actual object resides in the client's space.

It achieves this by forwarding calls made on it to the real object using the remoting

infrastructure

RealProxy

A RealProxy is an instance of a class that inherits from the abstract base class RealProxy

that is defined in the System.Runtime.Remoting namespace.

The real proxy accepts messages (IMessage) through its Invoke() method and forwards

them to a remote object. With this functionality the real proxies are the transport layer for

transparent proxies. However, they not only do the bulk of the work for the transparent

proxies, they are also the "factories" to create them. The RealProxy base class is able to

dynamically create a transparent proxy for any arbitrary .NET class-type through

metadata and .NET Reflection and have that transparent proxy call the real proxy's own

Invoke() method.

The RealProxy implements a part of the functionality that is needed to forward the

operations from the transparent proxy. Note that a proxy object inherits the associated

semantics of managed objects such as garbage collection, support for fields and methods,

and can be extended to form new classes. The proxy has a dual nature: it acts as an object

of the same class as the remote object (transparent proxy), and it is a managed object

itself.

Channels:

Channels are responsible for transporting messages. As such, they are an abstraction of a

specific transport protocol and wrap the protocol to make it available to the .NET

Remoting infrastructure.

Page 15: Remoting Architecture in.Net

The .NET Framework comes with three built-in sets of channels: A TCP channel that

uses permanently-connected raw TCP/IP sockets and a HTTP channel that uses the

.NET HTTP infrastructure.

The channel model is also extensible; if you require support for other transport protocols,

you can implement your own channels and use them with all the parts of the .NET

Remoting infrastructure.

A channel is responsible for establishing endpoint-to-endpoint communication. The

transport portion of the channel implementation is handed a formatted data stream and is

responsible for getting that formatted data stream to the other side. On the other hand, it

will receive a formatted data stream from another endpoint and is responsible to deliver

that to its host application domain.

Channels can listen for messages and send messages. The listener portion of a channel

implements the IChannelReceiver interface and the sender portion implements the

IChannelSender interface. A channel is only bi-directional it implements both

interfaces. If you want, for some reason, to implement a receive-only channel you only

need to implement the IChannelReceiver interface and IChannelSender for a send-

only channel, respectively. A receive-only channel can, of course, not relay any call

backs.

As previously mentioned, you can also write your own channels, if you need to transmit

data over protocols not covered by the core .NET Framework, for instance, APPC, IPX or

Windows Named Pipes.

For your own channel implementation you must implement either the

IChannelReceiver or the IChannelSender interfaces, or both, depending on whether

the channel is going to be bi-directional or unidirectional.

System.Runtime.Remoting. ChannelServices

The ChannelServices class serves to manage and register .NET Remoting channels. You

can register any number of channels with the channel services. These channels are global

for your application domain and define the transport endpoints that your application

exposes.

If you register a TCP channel on port 8085 and a HTTP channel on port 8080, all object

endpoints that have been registered with RemotingServices will be equally available on

both channels

Channel Sinks

Most of the functionality that was explained above will not work until this is actually

implemented in a chain of channel sinks. A channel sink is a pluggable component that is

provided to the channel through a channel sink provider class.

Page 16: Remoting Architecture in.Net

A channel sink provider class implements the interface IClientChannelSinkProvider

if it generates sinks for the client side of a channel and implements

IServerChannelSinkProvider if it generates sinks for the server side. The sinks

themselves implement IClientChannelSink and or IServerChannelSink.

When a channel is created, you will, as in the case of the Http Channel or Tcp Channel,

be able to pass an implementation of either or both interfaces to the channel, letting you

install your own channel sink.

Channel sinks may implement interception, security checks, logging or whatever else you

want to control or monitor regarding Remoting traffic.

A very special case is of formatter sinks. These are provided by implementations of either

IClientFormatterSinkProvider or the IServerFormatterSinkProvider interfaces

and perform the conversion from and to the wire-format. A formatter sink implements

IClientFormatterSink and/or IServerFormatterSink.

When a channel is constructed, the providers are asked to provide channel sinks, which

are then linked into a chain of sinks. A call from a client will then be routed from the

proxy to a formatter sink (or a custom formatter sink that is placed before the formatter

sink), then to possibly existing custom sinks and finally to the transport sink that will

typically be provided by the channel implementation. On the receiving end, the channel

architecture works similarly in the other direction.

Formatters

Formatters are dynamically used by the channel architecture. You configure a channel to

transport messages in a certain wire format by associating it with a formatter other than

its default through the Remoting configuration facility. The channel will then pick the

associated formatter to render messages into the desired format.

Formatters are implemented through so-called sinks. Essentially, a channel employs a

sequence of these sinks, which work hand-in-hand to inspect an IMessage for logging and

security purposes, turn it into a wire-format and send it off to the receiver.

On the receiving end, the formatter acts as a de-serializer component that understands a

certain wire format and is able to translate that into a .NET message object implementing

IMessage.

The .NET Framework has two built-in formatters namely binary and SOAP. The binary

formatter uses a very compact binary format that is designed for best performance in

high-speed LAN environments and to interconnect .NET systems. The SOAP formatter

uses the XML-based Simple Object Access Protocol to transport object calls over the

Internet and to integrate .NET systems with all other systems in the enterprise

environment. The built-in formatter types are, of course, pre-registered with the system.

Page 17: Remoting Architecture in.Net

Custom Formatters allow talking to any endpoint

The formatter model is extensible. If you want to integrate systems directly using other

wire formats (to name a few: IIOP, RMI, ORPC, XP, XML-RPC) you could implement

your own formatters and have .NET systems talk natively to any endpoint you want.

TCP channel uses plain TCP sockets and transmits, by default, a compact, binary wire

format, provided by the BinaryFormatter object.

However, if you want to link .NET Framework-based systems in a LAN environment, the

TCP channel and binary formatter will yield the highest performance

The default wire format is an implementation of the SOAP 1.1 standard, which is

provided by the SoapFormatter class located in the namespace "System.Remoting.

Serialization.Formatters.Soap".

By now we have learned about messages that are key/value pair dictionaries and about

channels that somehow receive these messages, pass them to formatters to render them

into a wire format and then transport them to the destination.

On the receiving end, the wire format message is received by a channel and deserialized

by the formatter into the message object.

To use channels, client code drops off messages into the Remoting infrastructure using

the SyncDispatchMessage() or AsyncDispatchMethod() method on the

ChannelServices class, which resides in the System.Runtime.Remoting namespace.

As its name implies, SyncProcessMessage processes the request message in a

synchronous manner by passing that message to the next sink's SyncProcessMessage

method, where NextSink is a property in the same class pointing to the next sink in the

channel sink chain.

The IMessageSink interface is implemented by channels and the Remoting infrastructure

to accept messages

The IMessageSink interface has a NextSink property, which enables chains of message

sinks to be built. Message chains are a very common design pattern throughout the

Remoting infrastructure. When implementing your own message sink you must therefore

honour the NextSink property, by passing onward to the next sink any message which

you do not want to handle yourself.

Member Member Type Description

NextSink Read-only

property

The next message sink in the chain, or null if this

is the last sink in the chain

AsyncProcessMessage Method Processes the message asynchronously

Page 18: Remoting Architecture in.Net

SyncProcessMessage Method Processes the message synchronously

It is, however, perfectly legal to intercept, modify or process any message received in a

message sink implementation instead of passing it through to the ultimate destination.

If an unbound class has no serialization support, it cannot be marshalled and will cause a

remote method invocation to fail, if it as used as an argument or return value.

Adding serialization support to a class requires setting the "[serializable]" attribute

on the class and, optionally, implementing the ISerializable interface of the class. This

allows Formatters to use the serialization support of the Runtime to render the class

content in XML or a binary data stream, which can then be translated into the formatter's

native wire format.

Dispatcher

The Dispatcher is the proxy's counterpart at the receiving end of the communication and

located at the channel endpoint.

The Dispatcher's capabilities are provided by the StackBuilderSink class that is located

in the System.Runtime.Remoting.Messaging namespace.

The dispatcher

• Receives messages,

• builds stack-frame,

• invokes method

• Collects result

• and creates response message

Whenever one of those two methods (Method A or Method B shown in the above figure)

is called, the passed message object is decoded and the Dispatcher locates the object it

Page 19: Remoting Architecture in.Net

that is referenced in the call, dynamically creates a stack frame that contains all

arguments and executes the requested method.

When the method call returns, it collects the output parameters and the return value and

creates a response message with these parameters. The dispatcher will, of course, convert

marshal by reference object into references, which in turn are passed over the network

and "proxied" on the receiving end. The response message is then handed back to the

caller.

Below is a graphical representation of the flow. The message which arrives at the

receiving end of a channel, is serialized and formatted into a message object and is passed

to the StackBuilderSink.SyncDispatchMessage() method. The call is dispatched on

the real object and all values that must be returned are collected and sent back as a

response through the channel.

Let us assume we already have a transparent proxy that we can call. When we call the

method "MethodA()" on the transparent proxy, it formats the method name and the

arguments if such are present, into a IMessage format, and forwards them to the real

proxy's Invoke() method. The real proxy then drops this message into the

IMessageSink of the channel through the sink's SyncProcessMessage() method. Since

.NET makes no assumptions about the endpoint architecture, we're not doing this either,

and just assume that the message will somehow be responded. Actually this message

object will be parsed by each sink shown in the above figure until the sink chain ends or

server object reaches and in a similar manner it navigates back to the client object too.

Once the real proxy receives the response message, it will pass the response message on

to the transparent proxy, which will push the return values on the stack. With that, the

calling code will believe that it just called a local method.

When a channel receives a message that contains an object reference (an instance of the

ObjRef class), the reference information also contains the type of the referenced object.

With that data type in hand, the channel will create a new RealProxy instance and asks it

to create a new transparent proxy based on the metadata of that data type. This

transparent proxy object is then passed on to the called method

Page 20: Remoting Architecture in.Net

Declaring Methods "One-Way"

You can declare methods one-way using the "[oneway]" attribute on the message. When

this attribute is present on the method, the dispatcher will not collect any return value

information and the proxies will not wait for such information to arrive and return

immediately to the caller.

If a OneWay method throws an exception this exception will not be propagated to the

client.

The Call Context

A very valuable tool is the call context. (Do not confuse this with the .NET Remoting

context) The call context allows you to add invisible arguments to a method call. While

there will only be rare uses in end-to-end communication, the call context is a true

lifesaver when you are using context interception and take advantage of the extensibility

mechanisms and the message chain that we are going to discuss in the now following

section.

Each message object automatically contains a dictionary entry "__CallContext" that

holds an instance of the type "CallContext"

The CallContext class is a utility class in the namespace System.Runtime.

Remoting.Messaging. We can add data to the context with CallContext.SetData(),

and reading the data can be done with CallContext.GetData().

A class that can be passed with the call context must implement the interface

ILogicalThreadAffinative. This interface doesn't define a single method; it is just a

marker to the .NET Remoting runtime. A logical thread can spawn multiple physical

threads as such a call can cross process boundaries, but it is bound to a flow of method

calls. Implementing the interface ILogicalThreadAffinative in a class means that

objects of this class can flow with the logical thread. Additionally, the class is marked

with the [Serializable] attribute, so that the object can be marshaled into the channel

Remoting Services

The System.Runtime.Remoting namespace contains a couple of so-called service

classes that allow you to configure and tweak the runtime behaviour of the Remoting

system.

If the activator has determined that an object needs to be created or accessed remotely, it

forwards the call to the Connect() method on the RemotingServices class.

Page 21: Remoting Architecture in.Net

Connect() provides low-level access to Remoting and lets you activate objects remotely

even if the class is not configured to be remote in your application domain. The

Connect() method takes an argument of type System.Type (or a string representation

thereof) and an endpoint URI as arguments. The return value is a properly proxied object,

if the call succeeds.

The type information is used to extract the metadata from an Assembly to create the

transparent proxy from the real proxy. Therefore, the metadata of the remote class must

be available to the client at runtime. This does not mean, though, that the client must

possess the actual server implementation Assembly. The client side may rather have a

reduced copy of the metadata that only describes the full structure and that is sufficient

for the proxy to build a structural image of the remote class.

One way to do this is to use the soapsuds utility that is included with the .NET

Framework SDK. The easiest way to build a metadata-only Assembly is:

soapsuds –ia:<inputAssemblyName> -oa:<outputFile>

Known Common Error Messages

If the connection string that is used with the Connect() method is wrong, we get an error

the first time that a remote method is called. The possible error messages we can get are

listed here:

1.SocketException: No such host is known.

This error message occurs when the host name cannot be resolved.

2.SocketException: No connection could be made because the target machine actively

refused it.

If the specified port number is incorrect or the server is not started, we will get this error

message.

3.RemotingException: Object <Name> has been disconnected or does not exist at the

server.

This error message occurs if the name of the endpoint is incorrectly specified, or when

the leasing time has expired when using a client-activated object.

System.Runtime.Remoting.TrackingServices

Page 22: Remoting Architecture in.Net

The tracking services serve to "track" almost everything that is happening in the

Remoting subsystem. Whenever an object becomes disconnected (after its lease has

expired or a connection is broken) or when an object has been marshalled or unmarshaled

(a proxy has been built), the tracking services will invoke a user provided implementation

of the ITrackingHandler interface. This interface defines three methods that are called

by the remoting infrastructure when marshalling and unmarshalling occurs:

We can register an implementation of ITrackingHandler by the following code snippet

TrackingServices.RegisterTrackingHandler(new MyTrackingHandler());

Where MyTrackingHandler is the implementation of ITrackingHandler

Asynchronous Remoting

Calling remote methods across the network can take some time. We can call the methods

asynchronously, which means that we start the methods, and during the time the method

call is running on the server we can do some other tasks on the client. .NET Remoting

can be used asynchronously in the same way as local methods.

Calling Remote Methods Asynchronously

The same programming model used for local calls can also be used for remote calls. We

will extend the remoting example by using some arguments and return values with a

remote method. First, we extend the remote object class RemoteObject with the long-

running method MyMethod(). Nothing else changes with the server.

// RemoteObject.cs

// ...

public int Mymethod(int val1, int val2, int ms)

{

Thread.Sleep(ms);

return val1 + val2;

}

In the client program, we have to declare a delegate with the same parameters as the

Mymethod() method:

Page 23: Remoting Architecture in.Net

// SimpleClient.cs

// ...

class SimpleClient

{

private delegate int MyMethodDelegate(int val1, int val2,int ms);

In the Main() method after creating the remote object we create an instance of the

delegate and pass the method Mymethod to the constructor:

static void Main(string[] args)

{ RemotingConfiguration.Configure("SimpleClient.exe.config");

RemoteObject obj = new RemoteObject();

MymethodDelegate d = new MyMethodDelegate (obj.Mymethod);

}

}

The remote method can now be started asynchronously with the

BeginInvoke()

method of the delegate class. Here we pass the values 3 and 4 to add

with a

sleep time of 100 ms. The method BeginInvoke() will return the control

immediately initialising the execution of Mymethod method; The main

thread

will continue it's execution with other statemets.

IAsyncResult ar = d.BeginInvoke(3, 4, 100, null, null);

Console.WriteLine("Method started");

To get the result that is returned with the method Mymethod() we have to wait until the

method is completed. This is done using ar.AsyncWaitHandle.WaitOne(). Calling the

delegate method EndInvoke() we get the result that is returned from Mymethod().

ar.AsyncWaitHandle.WaitOne();

if (ar.IsCompleted)

{

Console.WriteLine("Method finished");

int result = d.EndInvoke(ar);

Console.WriteLine("result: " + result);

}

Call backs with Delegates

.NET Remoting supports two types of call backs: with remote objects that are passed to

the server, and with delegates. Using a delegate we can pass an AsyncCallback delegate

when calling the method BeginInvoke() to have a call-back when the asynchronous

remote method completes. We have to define a method that has the same signature and

return type that the delegate AsyncCallback defines. The delegate AsyncCallback is

defined with this signature in the assembly mscorlib:

public delegate void AsyncCallback(IAsyncResult ar);

Page 24: Remoting Architecture in.Net

We implement the method MyMethodCallback that has the same signature and return

type. The implementation of this method is similar to how we handled the asynchronous

method in the last code sample. It doesn't matter if the method is implemented as a class

method or an instance method. We only need access to the delegate that is used to start

the remote method. To make the delegate available to the static method we'll now

declared as static member variable:

private delegate int MymethodDelegate(int val1, int val2, int ms) {

private static MymethodDelegate d;

public static void MymethodCallback(IAsyncResult ar)

{

if (ar.IsCompleted)

{

Console.WriteLine("Method finished");

int result = d.EndInvoke(ar);

Console.WriteLine("result: " + result);

}

}

}

In the Main() method, we have to create a new instance of the AsyncCallback delegate

and pass a reference to the function that should be called asynchronously. With the

BeginInvoke() method we pass the instance of the AsyncCallback so that the method

MymethodCallback() will be invoked when the remote method Mymethod() completes

static void Main(string[] args)

{

RemotingConfiguration.Configure("SimpleClient.exe.config");

RemoteObject obj = new RemoteObject();

d = new MymethodDelegate(obj.Mymethod);

AsyncCallback cb =

new AsyncCallback(SimpleClient.MymethodCallback);

IAsyncResult ar = d.BeginInvoke(3, 4, 3000, cb, null);

Console.WriteLine("Method started");