Quantcast
Channel: C# Help » Remoting
Viewing all articles
Browse latest Browse all 10

.Net Remoting – Part4 A Custom Proxy

$
0
0
RealProxy And TransparentProxy
The .Net Remoting Framework uses two proxy objects to acomplish its work of making a remote call from a client object to a remote server object. A RealProxy object and a TransparentProxy object. The RealProxy object does to work of actually sending messages to the remote object and receiving response messages from the remote object. The TransparentProxy interacts with the client and does to work of intercepting the remote method call made by the client.
A Custom Proxy
Why bother with a custom proxy? Just as with COM, the main reason is efficiency of marshaling. The standard .Net proxy can be replace with a custom proxy by inheriting from the RealProxy class. Load balancing can also be done in our custom RealProxy class, in addition, and more importantly, a custom proxy allows us access to the messages passed to and from remote objects.
// The Interface
using System;

namespace CustProxyLib
{
public abstract class BaseRemoteObject : MarshalByRefObject
{
public abstract void setValue(int pValue);
public abstract int getValue();
public abstract string DoWork(string s);
}
}

This is a typical interface we have seen before implemented by a SAO.
// The Server
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using CustProxyLib;

namespace CustProxyServer
{

class CustProxyServer : BaseRemoteObject
{
int mValue;

public override void setValue(int pValue)
{
Console.WriteLine("CustProxyServer.setValue old={0} new={1}", mValue, pValue);
mValue = pValue;
}

public override int getValue()
{
Console.WriteLine("CustProxyServer.getValue val={0}", mValue);
return mValue;
}

public override string DoWork(string s)
{
Console.WriteLine("DoWork method invoked on server");
return "Remote greetings from – " + s;
}

public CustProxyServer()
{
Console.WriteLine("CustProxyServer.ctor – remote singleton created");
}

} // class CustProxyServer

class CustProxyServerStarter
{
[STAThread]
static void Main(string[] args)
{
TcpChannel chnl = new TcpChannel(1200);
ChannelServices.RegisterChannel(chnl);

RemotingConfiguration.RegisterWellKnownServiceType(
typeof(CustProxyServer), "CustProxyServer.tcp", WellKnownObjectMode.Singleton );

Console.WriteLine("CustProxyServer Remote Server On Port 1200 (using Tcp Protocol)…");
Console.WriteLine("Press <enter> to exit");
Console.ReadLine();
}
}
}
</enter>

A simple server with a Singleton remote object, that implements our interface.
// The Client
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;

using CustProxyLib;

namespace CustProxyClient
{
public class CustomProxy : RealProxy
{
string _url;
string _uri;
IMessageSink _sinkChain;

public CustomProxy(Type type, string url)
: base(type)
{
_url = url;
IChannel[] registeredChannels = ChannelServices.RegisteredChannels;
foreach(IChannel chnl in registeredChannels)
{
if (chnl is IChannelSender)
{
IChannelSender chnlSender = (IChannelSender) chnl;
_sinkChain = chnlSender.CreateMessageSink(_url, null, out _uri);
if (_sinkChain != null)
break;
}
} // foreach
if (_sinkChain == null)
{
throw new Exception("No channel has been found for " + _url);
}
} // ctor

public override IMessage Invoke(IMessage msg)
{
IDictionary d = msg.Properties;
d["__Uri"] = _url;

// process the request mesage here
IMessage retMsg = _sinkChain.SyncProcessMessage(msg);
// process the return message here
return retMsg;
}
} // class CustomProxy

class CustProxyClient
{
[STAThread]
static void Main(string[] args)
{
TcpChannel chnl = new TcpChannel();
ChannelServices.RegisterChannel(chnl);

CustomProxy prx = new CustomProxy(typeof(BaseRemoteObject),
"Tcp://localhost:1200/CustProxyServer.tcp");
BaseRemoteObject brObj = (BaseRemoteObject) prx.GetTransparentProxy();

brObj.setValue(411);
Console.WriteLine("Custom Proxy Remote Server: {0} value:{1}",
brObj.DoWork("Narendra"), brObj.getValue());

}
}
}

The client is where we see a difference from the previous examples. We begin by inheriting from RealProxy. The constructor first calls the base RealProxy which uses the type to generate a TransparentProxy object. Then all of the registered channels are checked and the first one that parses the url properly returns an IMessageSink object. Next we override the RealProxy's Invoke(IMessage msg) method and use our newly created message sink to forward the message to the remote object. In the overidden Invoke() method we have complete access to both the request messages and the response messages. The msg parameter is what we send to the remote object and the return value of our call to IMessage retMsg = _sinkChain.SyncProcessMessage(msg); is the message returned by the remote object. Below is a diagram of the server and client.
Summary
We have seen quite a few things: There are two ways to marshal a remote object. MarshalByValue and MarshalByRefObject. There are three types of remote objects, SAO – Singleton, SAO – SingleCall and CAO. A remote object's lifetime is completed determined by the host application domain's lease manager object. The .Net Remoting Framework is extensible as we have senn the the above example. However there is a lot more to this topic than what is covered here, it is my hope that this elementary exposition will provide you with an entry to more moderate and advanced topics.
Appendix – COM
Recall the classic C++ definition of the IUnknown interface:

ass="smallestblack"> class IUnknown
{
virtual HRESULT QueryInterface (REFIID riid, void** pv) = 0;
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
};

The programmer was responsible for object lifetime management with its attendant network overhead. This was accomplished by reference counting using AddRef() and Release(). It is replaced by the decoupling of remote SAO and CAO objects from the client, and left to the Garbage Collector.

Viewing all articles
Browse latest Browse all 10

Trending Articles