Spl*_*ofy 8 .net c# remoting channels
我们在使用.NET Remoting时遇到了一个奇怪的问题.基本上,我们有一个服务器,它注册两个TcpChannels ChannelServices.RegisterChannel():
然后我们有一个客户端注册一个TcpChannel,以便能够与服务器通信.我们通过Activator.GetObject()使用URI 调用从服务器检索一个对象
"TCP:// SERVERIP:50000 /对象名"
这工作正常,客户端连接到端口50000上的服务器并获取对象.
但是,当我们开始调用该对象上的方法时,将丢弃与端口50000上的通道的连接,并自动在端口15000上建立与该通道的新连接.这对我们来说是一个真正的问题,因为我们不希望端口15000上的流量,因为该通道可能没有绑定到与服务器上的端口50000通道相同的网络适配器,或者该端口可能未在防火墙中打开,这会导致远程召唤自然失败.
这对我们来说非常奇怪,因为客户端在我们的代码中不知道端口15000上的服务器上存在另一个通道或它侦听的IP,但它尝试连接到它.
非常感谢任何帮助,
谢谢,卡斯帕
这是设置其中一个服务器通道的代码,通常在端口50000上:
IDictionary props = new Hashtable();
props["port"] = m_tcpPort;
props["name"] = String.Empty;
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
m_tcpChannel = new TcpServerChannel( props, /*clientProvider,*/ serverProvider );
ChannelServices.RegisterChannel( m_tcpChannel, false );
m_wellKnownObjRef = RemotingServices.Marshal( this, "Server@" + m_tcpPort.ToString() );
Run Code Online (Sandbox Code Playgroud)
这是设置其他服务器通道的代码,通常在端口15000上:
IDictionary props = new Hashtable();
props["name"] = String.Empty;
props["port"] = ip.Port;
props["bindTo"] = ip.Address.ToString();
props["timeout"] = REMOTING_TIMEOUT; // Timeout to prevent hung remoting calls.
if (!String.IsNullOrEmpty( machineName ))
{
props["machineName"] = machineName;
}
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
m_channel = new TcpChannel( props, clientProvider, serverProvider );
ChannelServices.RegisterChannel( m_channel, false );
m_objRef = RemotingServices.Marshal( this, QueueName ); // Queuename is a GUID.
Run Code Online (Sandbox Code Playgroud)
这是客户端中连接到第一个服务器通道的代码,通常在端口50000上:
IDictionary props = new Hashtable();
props["port"] = 0;
RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off;
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
m_tcpChannel = new TcpClientChannel(props, clientProvider/*, serverProvider*/);
ChannelServices.RegisterChannel(m_tcpChannel, false );
string address = "tcp://" + profile.RemoteIP + ":" + profile.RemoteTCP;
m_server = (Kernel)Activator.GetObject(typeof(Server), address + "/Server@" + port);
Run Code Online (Sandbox Code Playgroud)
我们已经与Microsoft签署了一个支持案例,显然,.NET Remoting不支持我们在这里做的事情.您只能在一个AppDomain中注册每种类型的一个通道.Remoting做的是它将对象的URI发送回客户端,告诉它可以访问相关对象的位置.当它这样做时,它会查看服务器端的注册通道,并使用它在那里找到的第一个匹配所请求类型的通道(在我们的例子中:Tcp).换句话说,它将使用任何正在首先注册的频道.它根本不关心客户端连接的通道.
解决方案是在客户端实现您自己的IClientChannelSinkProvider.实现CreateSink()方法时,您可以选择在创建要使用的接收器时希望客户端连接到的URL.