Click here to Skip to main content
6,305,776 members and growing! (17,179 online)
Email Password   helpLost your password?
General Programming » Internet / Network » Remoting     Advanced

.NET Remoting Message Redirection Channel Sinks

By zhi

An upper logic layer transparent way to redirect .NET remoting calls, enabling exposure of .NET remoting services behind firewall/NAT, to anywhere.
C#, VC7, VC7.1, Windows, .NET 1.0, .NET 1.1, Dev
Posted:20 Jun 2003
Views:56,528
Bookmarked:24 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
18 votes for this article.
Popularity: 4.22 Rating: 3.36 out of 5
5 votes, 27.8%
1
1 vote, 5.6%
2
3 votes, 16.7%
3
2 votes, 11.1%
4
7 votes, 38.9%
5

Introduction

.NET remoting is a beautiful framework, but its most serious deficiencies preventing it from being useful in today's Internet environment, is that it requires each node to have a global IP, so direct TCP connections can be made. Other incomplete solutions aimed at this problem exist (GenuineChannel), but they use special transport channels (instead of the standard TCP/HTTP), with large amount of unproven custom code, thus make your code heavier and unstable. These solutions also do not let 2 objects both behind firewall call each other, either.

Reachability channel sinks provide a more lightweight, elegant solution. Remoting objects hosted by machines with only local IPs behind firewalls can be made reachable from anywhere (including those machines behind firewalls themselves), using standard transport channels, by a Message Redirector. The whole process is transparent from upper, logic layers. Asynchronous calls, one-way calls are also supported.

Advantages of .NET remoting

.NET remoting has the the following advantages:

  • Separation of network-code from logic code.
  • Advantage over WebService: Clients can receive events from server. More types can be passed. Higher throughput.

Although .NET remoting is designed to accommodate the need of Enterprise intranet applications, nothing prevents it from being used over the Internet, at least not security problems - it is free from security holes - buffer overrun is impossible in managed code in which .NET remoting framework is entirely written. .NET remoting is ideal for peer-to-peer applications, because it alleviate programmers from writing complex network code that manages complex network topologies.

How to use in your project

Configuration files

  • For hosts who are behind firewall and need to expose objects:
    <appSettings>
      <add key="RedirectorURL" 
        value="tcp://Redirector's IP:Port/Redirector.rem" />
    </appSettings>
    ....
       <serverProviders>
         <provider type="Reachability.ServerSinkProvider, Reachability" />
           <formatter ref="binary" />
       </serverProviders>
  • For hosts who need to call objects through Redirector:
    <clientProviders>
          <formatter ref="binary" />
            <provider 
             type="Reachability.ClientSinkProvider, Reachability" />
    </clientProviders>
  • For Redirector:
    <wellknown mode="Singleton" 
            type="Reachability.Redirector, Reachability" 
        objectUri="Redirector.rem" />
    ...
             <channels>
               <channel ref="tcp" port="Redirector's Port" >
                <serverProviders>
           <formatter ref="binary" />
         </serverProviders>
         <clientProviders>
          <formatter ref="binary" />
         </clientProviders>
        </channel>
        
             </channels>

Code needed

Add reference of Reachability.dll to your project.

Hosts which need to expose objects via the Redirector must call Reachability.ServerSinkProvider.StartWaitRedirectedMsg() after RemotingConfiguration.Configure(), or after RemotingServices.Marshal(). The effect of this call is to start receiving messages from the Redirector.

How it works

There are already many articles on how .NET remoting works and on channel sinks, and I don't have time to repeat such descriptions here. The Reachability sinks have 3 components:

  1. The Redirector service
  2. The "Server" Channel Sink
  3. The "Client" Channel Sink

Basically, server sink adds reachability information (i.e. via which Redirector can we send message to this object) to (ChannelData in ) the ObjRef. When this ObjRef is passed to somewhere, there, the client sink finds out that reachability information attached to the ObjRef, and instead of directly trying to connect to the object, it pass the call to the Redirector. The Redirector will deliver the call appropriately, provided the host which created the ObjRef is listening on the Redirector properly. (This is done by StartWaitRedirectedMsg()).

Here is the heart of the code that makes hosts behind firewall receive calls (without special transport channel):

public void RedirectRequest(Guid slot, bool oneway, 
     ITransportHeaders requestHeaders, byte[] requestStream, 
     out ITransportHeaders responseHeaders, out byte[] responseStream)
{
   SyncQueue q = reqs[slot] as SyncQueue;  
   if(q==null)reqs.Add(slot, q=new SyncQueue());
   q.Enqueue(new Message(requestHeaders, 
       requestStream, Thread.CurrentPrincipal, oneway));
   
   if(!oneway)
   {
      q = resps[slot] as SyncQueue;   
      if(q==null)resps.Add(slot, q=new SyncQueue()); 

      Response r = q.Dequeue() as Response;
      responseHeaders = r.responseHeaders;
      responseStream = r.responseStream;
   }
   else
   {
      responseHeaders = null;
      responseStream = null;
   }
}
.....
   static void WaitForRequest(object o)
   {
      Redirector r = Activator.GetObject(typeof(Reachability.Redirector), 
                     RedirectorUrl) as Reachability.Redirector;
      Redirector.Message m;
      try
      {
         while(true)
         {
            r.GetNextRequest(rdata.Slot, out m);
            if(m==null)break;
          // must place this sink after formatter before

          // server transport, so message goes into stream.

            IMessage respMsg;    

                ITransportHeaders respHeader;
                Stream respStream;
            ServerChannelSinkStack stack = 
                  new ServerChannelSinkStack();     
                stack.Push(new ServerSink(theSink),r);
     
               theSink.ProcessMessage(stack,null,
                 m.requestHeaders,
                 new MemoryStream(m.requestStream),
               out respMsg, out respHeader, out respStream);
               if(!m.oneway)
               {
                    r.ReturnResponse(rdata.Slot, 
              new Redirector.Response(respHeader, respStream));
           }
        }
     }
     catch(Exception e){
        System.Diagnostics.Trace.Write(e.ToString());
     }
   }

The node behind firewall will not listen for incoming calls, instead it calls GetNextRequest() and blocks till an incoming call arrives (like the Windows API GetMessage()). The Redirector is blocked until ReturnResponse() is called.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

zhi


Member
My name is Zhiheng Cao. I major in Eletronics Engineering, in University of Tokyo. I do part time jobs of computer programming and teaching high school students English and Mathematics.

CodeProject provided me with valuable information for my programming job many times in the past. I hope I can do my part by providing goodies I have.


Occupation: Researcher
Location: United States United States

Other popular Internet / Network articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 25 (Total in Forum: 25) (Refresh)FirstPrevNext
GeneralBecause of security restrictions, the type System.Runtime.Remoting.ObjRef cannot be accessed. PinmemberAlexsandro_xpt16:12 30 Jun '09  
JokeIt Works! PinmemberSpungin20:11 8 Mar '09  
GeneralZHI, please reply if you are still around... Pinmemberkdubious18:10 9 Aug '08  
QuestionIs their a way to get the client to not open a listening socket Pinmemberpiba11:41 6 May '08  
QuestionStarting client events from server PinmemberDamz8:13 19 Sep '07  
Generalserver not processing any request when client is not reachable Pinmembermanish barai2:40 23 Jun '07  
GeneralMore sample code requested Pinmemberboboruba1:12 28 Feb '07  
GeneralRe: More sample code requested Pinmemberpiba11:26 6 May '08  
GeneralTrying to make it work. PinmemberMihaiMarin2:59 20 Apr '06  
GeneralMore details please Pinmemberlangdeng20:32 17 Oct '05  
GeneralI found better stuff : www.dotnetremoting.com PinsussTcheck19:09 31 Jan '05  
GeneralRe: I found better stuff : www.dotnetremoting.com PinsussAnonymous15:09 7 May '05  
GeneralRe: I found better stuff : www.dotnetremoting.com Pinsusso919:26 22 Oct '05  
Generala small question Pinmemberqnguyenhoang@yahoo.com0:03 17 May '04  
Generalmistake Pinmemberqnguyenhoang@yahoo.com0:05 17 May '04  
GeneralSecurity Exception PinmemberGery Dorazio17:29 20 Aug '03  
GeneralRe: Security Exception PinmemberMadShad200422:22 7 Apr '04  
GeneralIs this solution really useful? PinsussBill200220:05 26 Jun '03  
GeneralRe: Is this solution really useful? Pinmemberzhi6:02 28 Jun '03  
GeneralRe: Is this solution really useful? Pinmember_Bill2002_9:07 28 Jun '03  
GeneralRe: Is this solution really useful? Pinmemberzhi18:44 28 Jun '03  
GeneralRe: Is this solution really useful? PinmemberBill200220:23 29 Jun '03  
GeneralRe: Is this solution really useful? Pinmemberzhi6:38 2 Jul '03  
GeneralRe: Is this solution really useful? PinmembergunnarD15:49 11 Dec '06  
GeneralRe: Is this solution really useful? Pinmemberkdubious18:09 9 Aug '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 20 Jun 2003
Editor: Smitha Vijayan
Copyright 2003 by zhi
Everything else Copyright © CodeProject, 1999-2009
Web09 | Advertise on the Code Project