Reputation: 71
I am trying to build a very simple .Net remoting connection and can't seem to figure out the magic incantation.
I have a server side class that is meant to be a singleton and live for the duration of the service process.
public class MyRemoteServerClass : MarshalByRefObject
{
public void DoSomething()
{
System.Diagnostics.Trace.Assert(false);
}
public override object InitializeLifetimeService()
{
return null;
}
}
Based on my readings of .Net remoting, I wrote this code to instantiate and register the server class in the service:
static void Main(string[] args)
{
MyRemoteServerClass server = new MyRemoteServerClass();
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel, false);
string url = "tcp://localhost:8080/MyRemoteServerClass";
RemotingServices.Marshal(server, url, server.GetType());
System.Console.ReadLine();
}
I wrote this code in the .Net winforms client to invoke the 'MyRemoteServerClass.DoSomething' function:
private void button1_Click(object sender, EventArgs e)
{
string url = "tcp://localhost:8080/MyRemoteServerClass";
ChannelServices.RegisterChannel(new TcpChannel(), false);
MyRemoteServerClass root = Activator.GetObject(typeof(MyRemoteServerClass), url) as MyRemoteServerClass;
root.DoSomething();
}
The 'Activate.GetObject' call appears to get a proxy reference to the server 'MyRemoteServerClass' instance. However, when I call 'DoSomething' I get a "Requested Service not found" exception.
{System.Runtime.Remoting.RemotingException: Requested Service not found
Server stack trace: at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at RemoteExampleServer.MyRemoteServerClass.DoSomething() at RemoteExampleClient.Form1.button1_Click(Object sender, EventArgs e) in c:\Aaron\RemoteExampleClient\Form1.cs:line 30} System.Exception {System.Runtime.Remoting.RemotingException}
What am I doing wrong? Note, I've allowed access for these apps through the firewall (and I get the same behavior when I completely disable the firewall). I have no other security software on my computer.
Thanks,
Aaron
PS. I'd prefer solutions that don't involve modifications to the 'App.config' xml. If at all possible, I'd like the .Net remote connection to be configured in code-space.
Upvotes: 5
Views: 8043
Reputation: 1251
The problem is, on the server side, you're specifying the object's URI as its full URL. The URI in this case would be just "MyRemoteServerClass"
. So to fix it, change the server main method to:
static void Main(string[] args)
{
MyRemoteServerClass server = new MyRemoteServerClass();
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel, false);
string uri = "MyRemoteServerClass";
RemotingServices.Marshal(server, uri, server.GetType());
System.Console.ReadLine();
}
Note that on the client side, you're registering the channel in the button click handler. This will work only once; the second time the button is clicked, you'll receive an exception from RegisterChannel
because the channel "tcp" is already registered. To fix that you can replace the two lines with a single call to RemotingServices.Connect
, which will create the channel as necessary:
private void button1_Click(object sender, EventArgs e)
{
string url = "tcp://localhost:8080/MyRemoteServerClass";
MyRemoteServerClass root = RemotingServices.Connect(typeof(MyRemoteServerClass),
url) as MyRemoteServerClass;
root.DoSomething();
}
Upvotes: 3