我正在尝试建立一个非常简单的.Net远程连接,似乎无法弄清楚魔法咒语。
我有一个服务器端类,它应该是一个单例,并在服务过程中保持活动状态。
public class MyRemoteServerClass : MarshalByRefObject
{
public void DoSomething()
{
System.Diagnostics.Trace.Assert(false);
}
public override object InitializeLifetimeService()
{
return null;
}
}
根据我对.Net远程处理的解读,我编写了这段代码来实例化并在服务中注册服务器类:
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();
}
我在.Net winforms客户端编写了这段代码来调用'MyRemoteServerClass.DoSomething'函数:
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();
}
'Activate.GetObject'调用似乎获取服务器'MyRemoteServerClass'实例的代理引用。但是,当我打电话给'DoSomething'时,我会收到“未找到请求的服务”例外。
{System.Runtime.Remoting.RemotingException:找不到请求的服务
服务器堆栈跟踪: 在System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack,IMessage requestMsg,ITransportHeaders requestHeaders,Stream requestStream,IMessage& responseMsg,ITransportHeaders& responseHeaders,Stream& responseStream)
在[0]处重新抛出异常: 在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg) 在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData,Int32 type) 在RemoteExampleServer.MyRemoteServerClass.DoSomething() at RemoteExampleClient.Form1.button1_Click(Object sender,EventArgs e)在c:\ Aaron \ RemoteExampleClient \ Form1.cs:第30行} System.Exception {System.Runtime.Remoting.RemotingException}
我做错了什么?注意,我允许通过防火墙访问这些应用程序(当我完全禁用防火墙时,我会得到相同的行为)。我的电脑上没有其他安全软件。
谢谢,
亚伦
PS。我更喜欢不涉及'App.config'xml修改的解决方案。如果可能的话,我希望在代码空间中配置.Net远程连接。
答案 0 :(得分:1)
问题是,在服务器端,您将对象的URI指定为其完整URL。在这种情况下,URI只是"MyRemoteServerClass"
。因此,要修复它,请将服务器主方法更改为:
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();
}
请注意,在客户端,您正在按钮单击处理程序中注册该频道。这只会工作一次;第二次单击该按钮时,您将收到RegisterChannel
的异常,因为通道“tcp”已经注册。要解决此问题,您只需拨打RemotingServices.Connect
一次即可替换这两行,这将根据需要创建频道:
private void button1_Click(object sender, EventArgs e)
{
string url = "tcp://localhost:8080/MyRemoteServer";
MyRemoteServerClass root = RemotingServices.Connect(typeof(MyRemoteServerClass),
url) as MyRemoteServerClass;
root.DoSomething();
}