You are on page 1of 52

Introduction to .

NET Remoting

Brent Rector Wise Owl Consulting, Inc.

Brent Rector –

System software background
– Designed and written operating systems – Designed simulation and modeling languages and compilers – Windows expert since Windows 1.x beta - 1985

Wintellect instructor and speaker
– Conferences


WinDev, GeekCruises, WinSummit, VSLive

– ATL Internals – Addison-Wesley – Win32 Programming – Addison-Wesley – MSDN Magazine


Application domain is a hard boundary
– Acts much like a unmanaged process

– Also includes process/machine boundaries – No direct access to objects across boundary

Remoting services required to access an object across a hard boundary

Non-remotable objects

CLR objects cannot, by default, be used outside their AppDomain
– No way to copy them – No way to reference them

Exception occurs when you try to pass an object reference to a different domain

Remotable objects

Can request that instances of a class be accessible outside original AppDomain
– Should a client get a copy of the object? – Should a client get a reference (proxy) to the original object

. } Clients in foreign AppDomains receive clone .Serializable objects  When runtime can make a copy of the object. . an object can marshal-by-value to other AppDomains – Add SerializableAttribute – Or implement the ISerializable interface [Serializable] Class Foo {  .

from MarshalByRefObject.MarshalByRefObject { . .MarshalByRef objects  When the object's class derives. the runtime creates a proxy to the object // MBRO overrides // Serializable [Serializable] class Foo : System. }   Clients in foreign AppDomains receive proxy How does a client specify what proxy? . directly or indirectly. .

give the client [ a | this ] Calculator instance Connect to the "MathService" on server "LightningFast" using protocol HTTP on port 80 – Clients need to specify the desired object .Remoting in general  Clients must connect to servers – Server needs to publish an object I listen on this TCP channel and that HTTP channel I have a service called "MathService" When client connects to MathService using a supported channel.

Writing a server   Assumption: You have an assembly containing MarshalByRefObject types you wish to make available for use via remoting A server then becomes simply a host app – Loads the managed types – Configures remoting to expose the types   Can write your own host Can use IIS as an already available HTTP host .

Server design and implementation  Design considerations – Decide which channels/ports to support – Select an activation model – Decide how clients get type metadata  Implementation – Select/write appropriate host – Configure remoting system activation mode – Register channels .

Channels  A channel transports messages to and from a remote object – A server selects the channels upon which it listens for requests – A client selects the channels it wishes to use to communicate with the server  Runtime provides built-in channel types – HTTP and TCP channels – You can write custom channels .

Tcp.ChannelServices.RegisterChannel (new HttpChannel()).Remoting. .Runtime. .RegisterChannel (new TcpChannel(4242)). ChannelServices. .Channels. ChannelServices. using System.Runtime.Remoting.Remoting. using System.Remoting.Runtime.Channels.Channels.RegisterChannel using System. using System.Runtime.Http. .

Activation requests   Server also chooses how it wants to process activations requests for a type Two forms of server activation – WellKnownObjectMode.SingleCall – WellKnownObjectMode.Singleton  One form of client activation – Client activated object (CAO) .

SingleCall objects  Server's remoting layer creates one SingleCall object per method call – Each object services one and only one request Created on-demand as method calls arrive Lifetime limited to method call   Useful in stateless applications Best choice for load-balanced applications .

Singleton objects  Server's remoting layer creates one Singleton object – Sole object handles method calls from all clients Lifetime equals server lifetime  Useful in stateful applications – Can only store client-independent state  Best choice where overhead of creating and maintaining objects is substantial .

Well-known objects  Server activated types are "well-known" – Server tells remoting Here's a type Here's how and when to instantiate the type Here's the name (end point) a client will use to contact the type Connect to this server machine Get the (known) type at this end point (name) – Clients tell remoting .

Well-known objects  Server registers a well-known type using RegisterWellKnownServiceType specifying – The type being registered – The end point name known to clients – The activation model .

Calculator). . . .Runtime.SingleCall). WellKnownObjectMode.RegisterWellKnownServiceType(WKSTE). WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(typeof(WiseOwl. . RemotingConfiguration.RegisterWellKnownServiceType using System.Remoting. "EphemeralCalc".

RemotingConfiguration.Channels. System.Server activation example using using using using using System.Channels. ChannelServices.Remoting. System. WellKnownObjectMode. ChannelServices. Console.RegisterChannel(new TcpChannel(4242)).Runtime.Calculator).Tcp.Singleton). } } .Remoting.Http. System. System. WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(typeof(WiseOwl. class RemotingHost { static void Main(string[] args) { RemotingConfiguration.RegisterChannel(new HttpChannel(9000)). "SharedCalc".RegisterWellKnownServiceType(WKSTE).ReadLine().Runtime.Remoting.Runtime.Channels.Runtime.Remoting.ApplicationName = "WiseOwlMathService".

rem" or ".soap"  A TcpChannel requires the port number .Well-known object URLs  Server-activated objects are published at a URL – The URL is "well-known" to the client Such types are called well-known types The URL is called the well-known object URL ProtocolScheme://ComputerName:Port/PossibleApplicationName/ObjectUri  When IIS is the server's host: – PossibleApplicationName becomes virtual dir name – ObjectUri should end in ".

config" – E.config   Host must tell remoting to use the config file – RemotingConfiguration.g.Remoting config file  All hard-coded remoting information in prior example can reside in external config file – Default filename is executable plus ". RuntimeHost.exe is RuntimeHost.Configure (file) Server code simplifies… .exe.

Calculator.runtime.MathObjects" objectUri = "SharedCalc" /> </service> <channels> <channel port="9000" ref="http" /> <channel port="4242" ref="tcp" /> </channels> </application> </system.MathObjects" objectUri = "EphemeralCalc" /> <wellknown mode="Singleton" type="WiseOwl.Server remoting config file <configuration> <system.remoting> </configuration> .Calculator.remoting> <application name="WiseOwlMathService"> <service> <wellknown mode="SingleCall" type="WiseOwl.runtime.

RemotingConfiguration.Reflection.Remoting.GetExecutingAssembly().config"). class RemotingHost { static void Main(string[] args) { String s = Assembly.Configure (s + ". using System. } } .Runtime.ReadLine().Revised Server Example using System. Console.Location. using System.

Client activated objects    Server activated is one activation model Client activated is quite different Each client activation creates one object – Object's lifetime extends until the earliest event: – Similar to COM coclass activation semantics – Can store per-client state. receive constructor args Client drops reference to object Object's lease expires .

Lease based lifetime  Client activated object's lifetime controlled by a lease on the object – Leases have a lease time – Remoting infrastructure drops reference to object when lease expires  Each method call renews the lease – Use default renew on call time   Clients can renew the lease using the proxy Sponsors can renew the lease .

ActivatedServiceTypeEntry ASTE = new ActivatedServiceTypeEntry(typeof(WiseOwl.Runtime.RegisterActivatedServiceType(ASTE).Calculator)). RemotingConfiguration.Remoting.Registering Client Activated Objs  Server registers a client activated type using RegisterActivatedServiceType – Specifies the type being registered using System. . . . .

Channels. System.Channels.Channels.Remoting. RemotingConfiguration.ApplicationName = "WiseOwlMathService". System.Tcp. ActivatedServiceTypeEntry ASTE = new ActivatedServiceTypeEntry(typeof(WiseOwl. ChannelServices.Remoting.RegisterChannel(new TcpChannel(4242)).Runtime.Http. } } . System.Client activation example using using using using using System.Remoting.Runtime.Calculator)).Runtime.RegisterActivatedServiceType(ASTE ChannelServices.Remoting. class RemotingHost { static void Main(string[] args) { RemotingConfiguration. System. Console.ReadLine().RegisterChannel(new HttpChannel(9000)).Runtime.

Client activation URLs  Client activated objects do not need a unique URL for each object – PossibleApplicationName becomes virtual directory name when hosted in IIS – A TcpChannel requires the port number ProtocolScheme://ComputerName:Port/PossibleApplicationName .

Remoting config file 2  As before.MathObjects" /> </service> <channels> <channel port="9000" ref="http" /> <channel port="4242" ref="tcp" /> </channels> </application> </system.remoting> <application name="WiseOwlMathService"> <service> <activated type="WiseOwl.Calculator.runtime.remoting> </configuration> .runtime. all hard-coded remoting information can reside in external config file <configuration> <system.

Runtime.Remoting.config").Configure (s + ".GetExecutingAssembly(). Console. class RemotingHost { static void Main(string[] args) { String s = Assembly.Location. RemotingConfiguration.Reflection.ReadLine(). } } . using System.Revised Server Example  Server uses config file doesn't change! using System. using System.

GetObject Client can also obtain proxy using new – Client activated object factory exists at a URL Client requests factory to instantiate object and return a proxy to it using Activator.CreateInstance Client can also make same request using new .Remoting clients  A clients wants to use a remote object – Well-known objects exist at a URL Client obtains proxy using Activator.

Calculator) c.Activator.Calculator c = CType (o.Calculator).  No network traffic until first method call! – Proxy built on client from metadata – Server activates object on first method call .Add (42).GetObject  GetObject returns a proxy for the well-known type served at the specified location Dim o as Object = Activator. "http://localhost:9000/WiseOwlMathService/SharedCalc") WiseOwl. WiseOwl.GetObject ( GetType (WiseOwl.

Connect ( Type classToProxy. RemotingServices.Remoting.Runtime. – Which calls System.Unmarshal .Connect Using System. static object o RemotingServices. string url).Connect  GetObject is a thin wrapper over System.Runtime.Remoting.RemotingServices. RemotingServices.Remoting.Runtime.

RemotingServices.Unmarshal does the real work – Checks that type is MarshalByRef or Interface – Find or creates identity based on URI – Creates envoy and channel sink chains – Gets or creates transparent and real proxy  End results is client gets a proxy .Unmarshal  RemotingServices.

Activator.CreateInstance  Client activation requires a network round trip – Send activation message to server – Server creates object using specified constructor – Server builds ObjRef about new instance – Server sends message with ObjRef to client – Client creates proxy from ObjRef Can include constructor parameters .

Calculator) c. WiseOwl.Activator.CreateInstance(GetType(WiseOwl.Calculator).UrlAttribute("http://localhost:9000/WiseOwlMathService") } Dim o As Object = Activator.Calculator c = CType (o. . Nothing.Add (42). activationAttributes) WiseOwl.CreateInstance  CreateInstance returns a proxy to a new instance of the type served at the specified location Dim activationAttributes() As Object = { New _ Activation.

Remoting. WiseOwl.Remoting.Remoting.Runtime.GetObject(GetType(WiseOwl. uriWKO) ' Use the Calculator Dim c As WiseOwl.Channels System.Calculator) c.Add(21) End Sub End Class .Runtime.Channels.Runtime.RegisterChannel(New HttpChannel()) ' Connect to a Well-known object Dim uriWKO As String = "http://localhost:9000/WiseOwlMathService/SharedCalc" Dim o As Object = Activator.Channels.Complete client application I Imports Imports Imports Imports Imports System System.Calculator).Runtime.Calculator c = CType(o.Tcp Class RemotingClient Shared Sub Main() ' Register channel(s) ChannelServices.Remoting System.Http System.

Http System.Calculator) c.CreateInstance(GetType(WiseOwl.Calculator c = CType(o.UrlAttribute(url) } Dim o As Object = Activator.Remoting.Runtime.Channels.Calculator).Runtime.Remoting.Runtime.Complete client application II Imports Imports Imports Imports Imports  Still need to information runtime of proper channels to use System System. activationAttributes) ' Use the Calculator Dim c As WiseOwl.Channels. WiseOwl.Remoting.RegisterChannel(New TcpChannel()) ' Create a client activated object Dim url As String = "tcp://localhost:4242/WiseOwlMathService" Dim activationAttributes() As Object = { New Activation.Channels System.Remoting System.Add(21) End Sub End Class . _ Nothing.Tcp Class RemotingClient Shared Sub Main() ' Register channel(s) ChannelServices.Runtime.

runtime.MathObjects" url="http://localhost:9000/WiseOwlMathService/BadCalc"/> </client> </application> </system. all client remoting information can reside in external config file – RemotingConfiguration.remoting> </configuration> .BadCalculator.remoting> <application name="WiseOwlMathService"> <client url = "http://localhost:9000/WiseOwlMathService" displayName = "WiseOwlMathService"> <activated type = "WiseOwl.Calculator.Client's remoting config file  As with a server.runtime.Configure (file) <configuration> <system.MathObjects"/> <wellknown type = "WiseOwl.

Configure(s + ".Add(21) End Sub End Class .RemotingConfiguration.Remoting.Runtime.Assembly.BadCalculator = New WiseOwl.GetExecutingAssembly().Calculator() c.BadCalculator() b.Reflection.Add(21) ' Use the BadCalculator Dim b As WiseOwl.config") ' Use the Calculator Dim c As WiseOwl.Complete client application III  All remoting information from config file Class RemotingClient Shared Sub Main() ' Use remoting configuration in file Dim s As String = System.Calculator = New WiseOwl.Location System.

Runtime. delay-loaded client channels – HttpClientChannel and TcpClientChannel <channel ref="http client" displayName="http client (delay loaded)" delayLoadAsClientChannel="true" /> <channel ref="tcp client" displayName="tcp client (delay loaded)" delayLoadAsClientChannel="true" /> .Remoting.System.config configuration file defines two default. . System.Channels. <channel id="http client" type="System. .Remoting" /> <channel id="tcp client" type="System.Remoting.HttpClientChannel.Runtime.Runtime.Default client channels  Machine.TcpClientChannel.Tcp.Channels.Remoting" />  Must register explicit client channel to get callbacks or use a non-default channel type .Runtime.Http.

How does it work?  Client receives a proxy object when activating a remote object – Client "thinks" proxy is actual object  Proxy is instance of TransparentProxy class – Mimics inheritance hierarchy of remote object  A call on the proxy: – passes control to actual object when in same domain – creates an IMessage to object in different domain – Passes message to a RealProxy instance .

customized – For example. load balancing method calls.RealProxy class   RealProxy forwards msg to remote object – Handles all method calls to remote object RealProxy class can be extended. client side validation/processing of certain calls  TransparentProxy cannot be replaced – Internal remoting implementation class .

IsTransparentProxy  You can call IsTransparentProxy on any object reference to see if it is a proxy – Normally.IsTransparentProxy (Object o).Remoting. How does TransparentProxy know about the remote class? .  bool RemotingServices.Runtime. you don't care using System.

ObjRef   Runtime creates an ObjRef when you register an object with the remoting services An ObjRef contains all information required to locate and access a remote object – the strong name of the class – the class's hierarchy (its parents) – the names of all interfaces the class implements – the object URI – details of all available registered channels .

How to remote existing objects   Server/client activation expose "new" objects – What about existing objects? RemotingService.Marshal – Accepts a MarshalByRefObject – Registers it with remoting – Returns an ObjRef  RemotingService.Unmarshal – Accepts an ObjRef – Returns a proxy .

SoapFormatter sf = new System.Formatters. .FileStream fs = new System.FileStream (@"C:\ObjRef. sf.Close ().IO.Formatters.Runtime. or).Calculator calc = new WiseOwl.IO.IO. System. // Let the remoting layer (and the world) know about it ObjRef or = RemotingServices.Serialize (fs.Runtime.xml". WiseOwl.Create).RemotingServices. "ExplicitCalculator"). // Clients can now connect to the Calculator as a Well-known object // prot://machine:port/WiseOwlMathServices/ExplicitCalculator // Alternatively.FileMode.Marshal // // On the server.SoapFormatter ().Serialization.Serialization. System.Soap.Soap.Calculator (). we find our hero about to go public. . we can serialize and send the ObjRef to a client // System.Marshal (calc. fs. .

Formatters.FileStream("C:\ObjRef.Close() ' Done with the file ' Object is really an ObjRef but deserializes as the referenced type Dim c As WiseOwl.xml". System.IO.Serialization.Add(21) .Open) ' Deserialize the object in the file Dim o As Object = sf.Serialization.Calculator) ' Use the Calculator c.Runtime.RemotingServices.SoapFormatter sf = New System.Calculator = CType(o.SoapFormatter() ' Open a stream on the file Dim fs As System.FileStream fs = New System.Soap.Soap. WiseOwl.FileMode.Unmarshal ' ' There's an ObjRef serialized to a file using the SOAP formatter ' Get a formatter that can read the format Dim sf As System.Runtime.IO.IO.Deserialize(fs) fs.Formatters.

Client-side remoting     Client calls method on TransparentProxy TransparentProxy builds message – Stack frame to message     TransparentProxy passes msg to RealProxy RealProxy forwards msg to envoy sink(s) Last envoy sink forwards msg to context sink(s) Last context sink forwards msg to channel sink(s) Channel sinks turn message into a byte stream Last channel sink sends byte stream to server .

Server-side remoting   Channel receives a stream of bytes Channel forwards stream to channel sink(s) – Last channel sink converts stream into message   Last channel sink forwards msg to context sink(s) Last context sink forwards msg to server sink(s) – Last server sink is stack frame sink  Stack frame sink builds and issues call to requested method .

Remoting chain Message Transparent Proxy Real Proxy Envoy Envoy Envoy Sink Sink Sinks Tx Tx Context Sink Sink Sinks Formatter Sink 010110… Channel Transport Sink Channel Sink Channel Sink Client-side 010110… Server-side Transport Sink Channel Sink Channel Sink Channel Message Server object Stack Builder Sink Tx Tx Server Sink Sink Sinks Tx Tx Context Sink Sink Sinks Formatter Sink .

marshal by value or marshal by reference across an AppDomain boundary Three forms of activation – Server activated singleton – Server activated singlecall – Client activated .Summary   A class will either not marshal.