Link to home
Start Free TrialLog in
Avatar of DaFou
DaFou

asked on

Help on remoting

Ola,

I found a simple remoting example that consists of a remoting object a server and a client.
The client connects to the server that hosts the remoting object.

Now my question is how do I access the MethodIwantToRunRemotely in the server from the remoting object?
in other words:
How can I access the MethodIwantToRunRemotely method from the client via the remoting object?

here is the code:

// Remoting object
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace CodeGuru.Remoting
{
      public class SampleObject : MarshalByRefObject
      {
            public SampleObject()
            {
            }
            public string HelloWorld()
            {
                  return "Hello World!";
            }
      }
}

// Remoting server
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace CodeGuru.Remoting
{
      public class SampleServer
      {
            public static int Main(string [] args)
            {
                  TcpChannel channel = new TcpChannel( 8080 );
                  ChannelServices.RegisterChannel( channel );
                  RemotingConfiguration.RegisterWellKnownServiceType(
                        typeof( SampleObject ),
                        "HelloWorld",
                        WellKnownObjectMode.SingleCall
                  );
                  Console.WriteLine("Press the enter key to exit...");
                  Console.ReadLine();
                  return 0;
            }
            public static void MethodIwantToRunRemotely( string iStr )
            {
                  // do actions
            }
      }
}

// Remoting client
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace CodeGuru.Remoting
{
      public class SampleClient
      {
            public static int Main(string [] args)
            {
                  TcpChannel chan = new TcpChannel();
                  ChannelServices.RegisterChannel(chan);
                  SampleObject obj = (SampleObject) Activator.GetObject(
                        typeof(CodeGuru.Remoting.SampleObject),
                        "tcp://localhost:8080/HelloWorld"
                  );
                  if( obj.Equals(null) )
                  {
                        System.Console.WriteLine("Error: unable to locate server");
                  }
                  else
                  {
                        Console.WriteLine(obj.HelloWorld());
                  }
                  return 0;
            }
      }
}
Avatar of 123654789987
123654789987

The method MethodIwantToRunRemotely should be declared in SampleObject not in Server.cs

U have to add a delegate above SampleObject. Then declare a event in SampleObject


using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace CodeGuru.Remoting
{
public delegate void MethodIwantToRunRemotely(string s;
     public class SampleObject : MarshalByRefObject
     {
public event  MethodIwantToRunRemotely event;
          public SampleObject()
          {
          }
          public string HelloWorld()
          {
               return "Hello World!";
          }
     }
}

Then u have to handle that event in the client using a eventhandler

you don't even need delegates.  

public class SampleObject : MarshalByRefObject
     {
          public SampleObject()
          {
          }
          public string HelloWorld()
          {
               return "Hello World!";
          }
          public void yourMethod()
         {
               //do something
         }
     }

public class SampleClient
     {
          public static int Main(string [] args)
          {
               TcpChannel chan = new TcpChannel();
               ChannelServices.RegisterChannel(chan);
               SampleObject obj = (SampleObject) Activator.GetObject(
                    typeof(CodeGuru.Remoting.SampleObject),
                    "tcp://localhost:8080/HelloWorld"
               );
               if( obj.Equals(null) )
               {
                    System.Console.WriteLine("Error: unable to locate server");
               }
               else
               {
                    obj.yourMethod() //Server will execute this code
               }
               return 0;
          }

Avatar of DaFou

ASKER

123654789987, I have no idea what you mean. Please expand on the example

jjacksn, will yourMethod() that is a method in the remoting object be able to access vartiables inside of the server object?
I dont think so and thus your suggestion is not applicable.
DaFou, yes, that class can access anything on the server.  That class goes inside of a dll that is shared by the client AND server.  Anything you want to refer to, of course must be made to compile on the client side as well.  

The architecture I like to use for this goes as follows:

Inside the remoting class you have a class variable that is an an interface that implements everything you need.  this interface is in the shared dll, but the implementations of this interface are in other dlls that reside only on the server side.  You set the reference to the implementaiton of the interface in some server intializing code.  all remote methods pass the call through to this interface.  Thus, if you were to just create an object client side (without first setting up remoting) there would be a null pointer error because the internal interface implementation has not been set.  

This allows you to change the back end without changing the shared dll, as well keeping the information that is shared between the client and server to a minimum.  

I find this architecture clean, and you can easily change you code between CAO, singletons, and SAO.  To keep state in the remote object itself, you need to use CAOs.  
Avatar of DaFou

ASKER

Thank you jjacksn for your explenation.
I am afraid that I dont have enoug experiance with interfaces to set this up in the code snipets i posted.

Could you do the interface for void YourMethod() ? ( so creating the interface in the remoting object and having the server object listen to that interface )

That would answer my question
Interface are trivial, you just create a new class, and change the class keyword to interface.  write the signature for the methods you want, and then you can imlement the interface by using a colon after the class declaration.  

THIS IS IN THE SHARED DLL

public class SampleObject : MarshalByRefObject
     {
          public static YourInterface YourImplementation;  

          public SampleObject()
          {
          }
          public string HelloWorld()
          {
               return "Hello World!";
          }
          public void yourMethod()
         {
               YourImplementation();  
         }
     }

public YourInterface
{
          void YourMethod();
}

-------------------------------
THIS IS SERVER ONLY

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace CodeGuru.Remoting
{
     public class SampleServer
     {
          public static int Main(string [] args)
          {
               TcpChannel channel = new TcpChannel( 8080 );
               ChannelServices.RegisterChannel( channel );
               RemotingConfiguration.RegisterWellKnownServiceType(
                    typeof( SampleObject ),
                    "HelloWorld",
                    WellKnownObjectMode.SingleCall
               );
              // set the static instance
              SampleObject.YourImplmentation = new YourObject();

               Console.WriteLine("Press the enter key to exit...");
               Console.ReadLine();
               return 0;
          }
          public static void MethodIwantToRunRemotely( string iStr )
          {
               // do actions
          }
     }
}

//this means that you are implementing the interface YourInterface
public YourObject : YourInterface
{
     public void YourMethod()
     {
         //do something here
     }

}


--------------------------------
THIS IS CLIENT ONLY

public class SampleClient
     {
          public static int Main(string [] args)
          {
               TcpChannel chan = new TcpChannel();
               ChannelServices.RegisterChannel(chan);
               SampleObject obj = (SampleObject) Activator.GetObject(
                    typeof(CodeGuru.Remoting.SampleObject),
                    "tcp://localhost:8080/HelloWorld"
               );
               if( obj.Equals(null) )
               {
                    System.Console.WriteLine("Error: unable to locate server");
               }
               else
               {
                    obj.yourMethod() //Server will execute this code
               }
               return 0;
          }
Avatar of DaFou

ASKER

error messages i get when compiling the remoting object:
Expected class, delegate, enum, interface, or struct ( So i am guessing that 'public YourInterface' should be 'public interface YourInterface' )
The type or namespace name 'MarshalByRefObject' could not be found (are you missing a using directive or an assembly reference?)
Even after adding a reference to the remoting namespace

DaFou,

MarshalByRefObject is in the System namespace. You shouldn't need a reference to anything extra.  It must be spelled wrong.  

Yes, public YourInterface should be

public interface YourInterface
Avatar of DaFou

ASKER

Still in the remoting object:

'SampleObject.YourImplementation' denotes a 'field' where a 'method' was expected

public void yourMethod()
{
      YourImplementation();  ( this is the line that generates the error )
}

are you sure this works at your end? I am kinda expecting for the server not to work aswell as

public YourObject : YourInterface ( does this not mean inherit instead of implement interface? )
{
     public void YourMethod()
     {
         //do something here
     }
}


I am so sorry that I cannot solve these problem all by myself yet, but I am learning c# on basis of an application in where I need remoting.
next to a 40 hr job it is hard to figure out what is going wrong on my own :-(

Please help out a bit more, I hope we are getting close
ASKER CERTIFIED SOLUTION
Avatar of jjacksn
jjacksn

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial