Remoting
11.1 Introduction
Object running in one Virtual Machine (VM) should be able to access (call functions
on) objects that are in a different Virtual Machine. Usually this means the two
processes are running on two different computers. To set up remoting we proceed
as follows:
Instantiate target object (on server)
Setup our channels
Register our object (on server)
Get a reference to object (on client)
Call method on server from the client
For example on the Server side:
public class Server {
public static void Main() {
Target t = new Target();
RemotingServices.Marshal(t,"me");
IChannel c = new HttpChannel(8080);
ChannelServices.RegisterChannel(c);
Console.WriteLine("Server ready. ");
Console.ReadLine();
}
}
147
148 CHAPTER 11. REMOTING
On the Client side we have
public class Client {
public static void Main() {
string url = "http://localhost:8080/me";
Type to = typeof(Target);
Target t = (Target) RemotingServices.Connect(to,url);
Console.WriteLine("Connected to server.");
try {
string msg = Console.ReadLine();
t.sendMessage(msg);
} catch(Exception e) {
Console.WriteLine("Error " + e.Message);
}
}
}
A shared class (i.e. it is on the Client and Server side) is
public class Target : System.MarshalByRefObject
{
public void sendMessage(string msg)
{ System.Console.WriteLine(msg); }
}
Reference types passed via remoting must be serializable or marshal-by-reference.
Serializable == pass-by-value
Copy of object is made.
MarshalByRefObject == pass-by-reference
proxy object is passed.
An example for the second case is:
public class Counter : MarshalByRefObject {
int count = 0;
public void incCount() { count++; }
public int getCount() { return count; }
}
An example for the first case is:
11.1. INTRODUCTION 149
[Serializable]
public class Counter {
int count = 0;
public void incCount() { count++; }
public int getCount() { return count; }
}
We have to import:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http; // for Http
using System.Runtime.Remoting.Channels.Tcp; // for Tcp
Shared objects must be available to both the client and the server. Make a separate
assembly for it
csc /t:library Shared.cs
csc /r:Shared.dll Server.cs
csc /r:Shared.dll Client.cs
There are three main items in the process of remoting. The Interface, the Client
and the Server. The Interface is a .dll file (generated from a .cs file) which is on
the Client and Server side. The Server provides an implementation of the Interface
and makes it available to call. The Client calls the Server using the Interface.
150 CHAPTER 11. REMOTING
Example. The client provides a string to the server and the server returns the
length of the string.
We first create an interface with the file MyInterface.cs.
// MyInterface.cs
public interface MyInterface
{
int FunctionOne(string str);
}
MyInterface.cs is on the Server and Client side. We compile to MyInterface.dll
on the Client and Server side with
csc /t:library MyInterface.cs
On the Server side we now create our class which we invoke from a remote machine
(client). RemoteObject.cs is on the Server side and is the implementation of
MyInterface.cs.
// RemoteObject.cs
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
public class MyRemoteClass : MarshalByRefObject, MyInterface
{
public int FunctionOne(string str)
{
return str.Length; // length of string
}
}
Any class derived from MarshalByRefObject allows remote clients to invoke its
methods. Now on the Server side we compile
csc /t:library /r:MyInterface.dll RemoteObject.cs
This creates the file RemoteObject.dll on the Server side.
11.1. INTRODUCTION 151
Next we provide our Server on the Server side.
// ServerTcp.cs
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
public class MyServer
{
public static void Main()
{
TcpChannel m_TcpChan = new TcpChannel(9999);
ChannelServices.RegisterChannel(m_TcpChan,false);
RemotingConfiguration.RegisterWellKnownServiceType(
Type.GetType("MyRemoteClass,RemoteObject"),
"FirstRemote",WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Press ENTER to quit");
System.Console.ReadLine();
} // end Main
} // end class MyServer
First we create a TcpChannel object which we use to transport messages across our
remoting boundary. We select 9999 as the TCP port to listen on. This could cause
problems with firewalls. We use
ChannelServices.RegisterChannel
to register our TcpChannel with the channel services. Then we use
RemoteConfiguration.RegisterWellKnownServiceType
to register our RemoteClass object as a well-known type. Now this object can be
remoted.
We are using the string FirstRemote here which will be used as part of the URL
that the client uses to access the remote object. We use SingleCall mode here
which means a new instance is created for each remote call.
Remark. One could have also used Singleton in which case one object would have
been instantiated and used by all connecting clients.
Next we generate the exe file for ServerTcp via
csc /r:RemoteObject.dll ServerTcp.cs
152 CHAPTER 11. REMOTING
Now we write our Client program ClientTcp.cs on the client side.
// ClientTcp.cs
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
public class MyClient
{
public static void Main()
{
TcpChannel m_TcpChan = new TcpChannel();
ChannelServices.RegisterChannel(m_TcpChan,false);
MyInterface m_RemoteObject =
(MyInterface) Activator.GetObject(typeof(MyInterface),
"tcp://192.168.0.3:9999/FirstRemote");
Console.WriteLine(m_RemoteObject.FunctionOne("willi hans steeb"));
// for LocalHost
// "tcp://LocalHost:9999/FirstRemote");
} // end Main
} // end class MyClient
Just as in the Server we have a TcpChannel object, though in this case we do not
have to specify a port. We also use
ChannelService.RegisterChannel
to register the channel. We use
Activator.GetObject
to obtain an instance of the MyInterface object. The IP address of the remote
machine (Server) is 192.168.0.3 with the port 9999. The string FirstRemote
which forms part of the URL was that we passed to
RemotingConfiguration.RegisterWellKnownServiceType
on the Server.
To obtain the ClientTcp.exe file we run
csc /r:MyInterface.dll ClientTcp.cs
11.1. INTRODUCTION 153
To run everything on the Server side we enter the exe file at the command line
ServerTcp
Then on the Client side we enter the exe file at the command line
ClientTcp
Then we are provide with the length of the string. In the present case 16.
154 CHAPTER 11. REMOTING
Instead of using Tcp we can also use Http. Then the files ServerTcp.cs and
ClientTcp.cs are replaced by ServerHttp.cs and ClientHttp.cs shown below.
// ServerHttp.cs
// on Server side
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
public class MyServer
{
public static void Main()
{
HttpChannel chan = new HttpChannel(8080);
ChannelServices.RegisterChannel(chan,false);
RemotingConfiguration.RegisterWellKnownServiceType(
Type.GetType("MyRemoteClass,RemoteObject"),
"FirstRemote",WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Press ENTER to quit");
System.Console.ReadLine();
} // end Main
} // end class MyServer
11.1. INTRODUCTION 155
// Client.cs
// on client side
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
public class MyClient
{
public static void Main()
{
HttpChannel chan = new HttpChannel();
ChannelServices.RegisterChannel(chan,false);
MyInterface m_RemoteObject =
(MyInterface) Activator.GetObject(typeof(MyInterface),
"http://152.106.41.42:8080/FirstRemote");
Console.WriteLine(m_RemoteObject.FunctionOne("willi hans"));
// for LocalHost
// "tcp://LocalHost:9999/FirstRemote");
} // end Main
} // end class MyClient
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment