.NET Remoting переключение каналов само по себе

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

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

Затем у нас есть клиент, который регистрирует 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() );

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

person Sploofy    schedule 12.05.2010    source источник
comment
Если у вас есть какая-либо конфигурация канала в файле app.config, добавьте ее в свой вопрос.   -  person Hans Passant    schedule 12.05.2010
comment
Спасибо за ответ. Конфигурации app.config не существует, поскольку все это настраивается в коде. Я добавил этот код к вопросу.   -  person Sploofy    schedule 17.05.2010


Ответы (2)


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

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

person Sploofy    schedule 19.05.2010
comment
Спасибо за объяснение! Мы довольно долго искали, почему наш сервер не всегда правильно реагировал при создании каналов для нескольких сетевых адаптеров. Причина и решение были такими, как вы описали. - person Philippe; 30.10.2012

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

person ralf.w.    schedule 19.05.2010
comment
Само удаленное взаимодействие теперь устарело и заменено на WCF. - person John Saunders; 19.05.2010
comment
Это действительно так. Код, с которым у нас возникли проблемы, был написан еще тогда, когда только-только вышла .NET Framework 1.0. Кажется, никто не заметил этой проблемы в течение всего этого года, пока один из наших клиентов не попытался привязать два канала к разным сетевым адаптерам. - person Sploofy; 19.05.2010