.NET Remoting переключение каналов само по себе - PullRequest
8 голосов
/ 12 мая 2010

У нас странная проблема с .NET Remoting. По сути, у нас есть сервер, который регистрирует два канала TcpChannel с ChannelServices.RegisterChannel():

  1. Один слушает через порт 50000
  2. Другой слушает порт 15000.

Затем у нас есть клиент, который регистрирует канал TcpChannel для связи с сервером. Мы получаем объект с сервера, вызывая Activator.GetObject() с URI

"ТСР: // ServerIP: 50000 / имя_объекта"

и это прекрасно работает, клиент подключается к серверу через порт 50000 и получает объект.

Однако, когда мы начинаем вызывать методы для этого объекта, соединение с каналом через порт 50000 прерывается, и новое соединение устанавливается с каналом через порт 15000 автоматически. Это создает для нас реальную проблему, поскольку нам не нужен трафик через порт 15000, поскольку этот канал может быть не привязан к тому же сетевому адаптеру, что и порт 50000 на сервере, либо этот порт может быть не открыт в брандмауэре, что вызывает удаленное взаимодействие вызывает сбой естественно.

Это очень странно для нас, так как клиент не знает в нашем коде, что существует другой канал на сервере на порту 15000 или какой IP-адрес он прослушивает, но он пытается подключиться к нему.

Любая помощь в этом очень приветствуется,

Спасибо, Casper

Это код, который устанавливает один из каналов сервера, обычно на порт 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() );

Это код, который устанавливает другой канал сервера, обычно на порт 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.

Это код в клиенте, который подключается к первому каналу сервера, обычно к порту 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);

Ответы [ 2 ]

9 голосов
/ 19 мая 2010

Мы сообщили об этом в службу поддержки Microsoft и, по-видимому, то, что мы здесь делаем, не поддерживается .NET Remoting. Вам разрешено зарегистрировать только один канал каждого типа в одном домене приложений. Что делает Remoting, так это то, что он отправляет обратно URI объекта клиенту, чтобы сообщить ему, где он может получить доступ к рассматриваемому объекту. Когда он это делает, он просматривает зарегистрированные каналы на стороне сервера и использует первый найденный там канал, который соответствует запрошенному типу (в нашем случае: Tcp). Другими словами, он будет использовать любой канал, чтобы зарегистрироваться первым. Неважно, по какому каналу подключился клиент.

Решение состоит в том, чтобы реализовать свой собственный IClientChannelSinkProvider на стороне клиента. При реализации метода CreateSink () вы можете выбрать, к какому URL вы хотите подключиться клиенту при создании приемника.

0 голосов
/ 19 мая 2010

Я тоже боролся с этими "связанными" портами; Я думал, что это произойдет только в том случае, если сервер захочет что-то отправить назад (даже в процедуре события). Поскольку у меня всегда были проблемы с брандмауэрами, я переключился на GenuineChannels (хотя я думаю, что это немного устарело).

...