.Net Remoting continued


After several frustrating hours troubleshooting issues with objects flowing in both directions (i.e., From Client to Sever and vice versa), I have some more information that may help you.  This information is a continuation of the previous post on the subject found here.


 


In my previous posting I was primarily discussing activation of Client objects from a Server.  I have also found something interesting about the communication between a Client and a Server over a remoting Channel, where a client object is accessed from a Server (i.e., not activated by the Server but proffered up from the Client to the Server over the remoting channel).


 


Is this confusing enough?  Let’s use some pseudo-code to demonstrate the scenarios.


In the previous posting we spoke to the following scenerio.


 



  1. A Host process (let’s call this the “Client”) creates a remoting channel (IPC, TCP)


BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();


BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();


System.Collections.IDictionary props = new System.Collections.Hashtable();


props["portName"] = “SomeName”;


ichannel = new IpcChannel(props, clientProvider, serverProvider);




  1. The Host/Client starts another process (let’s call this the Server)


    1. The Server application creates a remoting channel


ichannel = new IpcChannel(props, clientProvider, serverProvider);





    1. The Server publishes a local MarshalByRefObject object (MBRO). Let’s call this ServerObject

RemotingServices.Marshal(ServerObject, @"UniqueIdentifier");


Or RegisterWellknownServiceType



  1. The Client activates the ServerObject and makes calls on the methods

ServerObject serverObj =  (ServerObject)Activator.GetObject(Type.GetType(AssemblyQualifiedNameOfObject), @"ipc://" + @"UniqueIdentifier"+ @"/ServerObject"));


serverObj.CallAMethod();


 



  1. If the Sever wishes to activate a MBRO in the Client process we need the following;


    1. The Client needs to create a server provider remoting channel

    2. The Client needs to publishes a local MBRO. Let’s call this ClientObject.

  2. The Server activates the ClientObject and now makes calls on the methods 

In order to enable this two-way activation we need to set the typeFilterLevel to Full. 


props["typeFilterLevel"] = "Full";


ichannel = new IpcChannel(props, clientProvider, serverProvider);


 


In the previous scenerio the Server can create MBRO’s and the Client can access the object methods over the channel.  In a new scenerio, where the Client creates a MBRO object and attempts to pass the object to a Server Object, you will receive the following error message – “Because of security restrictions, the type System.Runtime.Remoting.ObjRef cannot be accessed.” 


 


Note that this new scenerio the Server is not “activating” the Client object, but rather passing it to a Server object.  Surprisingly, even though you have a channel established and you can call in one direction (Client calling on the Server), with an object that is MBRO, it fails.  Doh!


 


We determined that we needed the typeFilterLevel property to be set to “Full” for the Server activating a Client object in the first scenerio.  In this second scenerio, we also need to set the following;  


serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;


 


Go figure <shrug>


 


It is apparent that there is a difference between the


["typeFilterLevel"] = "Full" property


and


the Serverprovider setting


BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();


serverProvider.TypeFilterLevel = TypeFilterLevel.Full;


 

I am not sure why these seemingly similar settings behave differently, but they do.  This may be a bug or intended behavior.  If I receive an answer on why they differ, I will post my findings.  In any event, I thought this might save someone else the frustration I experienced and also clear up my last posting where I insinuated that these settings are interchangeable.  And besides, you now you have another two-way remoting scenerio to add to your bag of tricks.

Comments (12)
  1. Dean Harding says:

    I do the same thing in one of my apps. It’s great for removing the need for polling in the client – the server can just call methods on the client whenever something the client is interested in happens.

  2. Mark Fox says:

    In this posting there are two sets of items 1,2,3. Are they both part of the solution or alternative ways of setting up a two way channel?

  3. Mark, If I understand your question correctly, I have shown 2 distinct methods of a "two-way" channel.

    The first scenerio shows the Server process activating an object in the Client process.  Note that this is activating an object, not passing an object through another object.

    The second scenerio shows a calling convention where a Client object (i.e., An object created in the Client process) is passed to the server object (i.e., An object instantiated in the Server Process) where the server can then call on the Client Object.

    Make sense?

  4. Jeevan Nagvekar says:

    Hi, I am trying out the two way remoting. I want to pass an object to server from client. I want the server call a method of that client object. I have created a class which both client and server understand. The client creates a instance of that class. In one remoting method, the client tries to call a method of remoting server and passes the object to server. But here the call fails. Any pointer to solution of this problem?

  5. Hi Jeevan,

    I’m not sure I understand your scenerio.

    I can’t determine whether you are expecting the client and/or Server to instantiate an object in both of the others process.  If this is the case then you need another channel to handle the incoming call.

    If you want the Server to instantiate an object on the Client (i.e., not passing it through an object already registered over a channel) then you will need another channel registered on the client to handle the incoming calls from the Server.  So you will have 3 channels – 1 for the Server and 2 for the Client.

    Else, if a client is activating an object that the Server has registered with the RemotingServices for Marshalling, then you need a channel in the server process and one in the client process.  If you wish to pass an object to the server from the client you can create the object (I assume it is MBRO) on the client and pass it to the Server object as a parameter to the Server object, then the Server can make calls on the client object.

    Then again your scenerio may not be as described above 😉 and your issue may be related to the typefilter settings I described.

    I realize my posts may have left a little to the imagination, so if I receive enough demand (the squeaky wheel gets the attention), I may spend the time working up some sample code.

  6. Vibhore says:

    Hey Jack,

    Do you have sample code which i can try?? Its really hard to find an example of how to make two way communication over IPC:( I dont want the client to keep polling the server. it would be really great if you can post a sample code.

    Thanks

    Vibhore

  7. Kate says:

    A sample that show how to implementthe second #1 a., b. and 2 would be great. since it is not clear how to create the server channel and publich the local MBRO in the client. Client call to server works but the other way? —

  8. Victor says:

    Vibhore,

    Look into remoting C# events. It’s a little tricky but provides an elegant way to handle subscriber/publisher scenarios.

  9. Monty says:

    I followed the steps mentioned by you but still not able to communicate both ways.

    The requirement of my project is that client calls the methods on server and also server calls a method on client. I tried passing client object to server but server cannot call the client.

    It would be great help if you could provide a sample working code so that I can learn from it and know where I am going wrong

  10. paresh masani says:

    Hi Jack,

    Could you please tell me how would i make the communication between two processes using IPC channel. Basically i want to pass the data between processes where server is one process and clients are several. Server should identify which message is belong to which client.

    Thanks,

    Paresh

  11. Paresh, the first part of your question is answered in the sample code I posted here (http://blogs.msdn.com/jackg/archive/2007/03/05/out-of-process-ipc-tcp-remoting-code.aspx ).

    In a nutshell, you need a startup object (i.e., a contract between 2 components) to get the communication process started.  

    The Host (i.e., Server) expects clients to implement this startup object, allowing the Host to call clients.  

    This allows the client to either provide a service to the Host and/or enables the Host to proffer up some functionality for the clients to consume (i.e., the Host provides some service).  

    In order for the Host to provide a service to the clients it uses this initial communication channel (i.e., the startup object) to pass serializable data and/or a  MarshalByRef object (e.g., remoteObject.RemoteMethod(hostObject)) through the startup object (e.g., RemoteObject).  Calls made by clients on the HostObject methods allow the client to call the Server/Host.

    On determining the client to send the message too – you could accomplish this a number of ways. You will need to keep track in some data structure the active clients and call the appropriate Client based on your notification scheme.

Comments are closed.

Skip to main content