Смешивание безопасных и незащищенных каналов - PullRequest
19 голосов
/ 30 марта 2010

Я не могу использовать незащищенный канал после того, как безопасный канал уже зарегистрирован. Приведенный ниже код работает, только если на стороне клиента ранее был зарегистрирован незащищенный канал.

Можно ли смешивать защищенные и незащищенные каналы без каких-либо ограничений на порядок регистрации?

using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

public class SampleObject : MarshalByRefObject
{
    public DateTime GetTest() { return DateTime.Now; }
}
public class SampleObject2 : MarshalByRefObject
{
    public DateTime GetTest2() { return DateTime.Now; }
}
static class ProgramClient
{
    private static TcpClientChannel RegisterChannel(bool secure, string name, int priority)
    {
        IDictionary properties = new Hashtable();
        properties.Add("secure", secure);
        properties.Add("name", name);
        properties.Add("priority", priority);
        var clientChannel = new TcpClientChannel(properties, null);
        ChannelServices.RegisterChannel(clientChannel, false);
        return clientChannel;
    }
    private static void Secure()
    {
        RegisterChannel(true, "clientSecure", 2);
        var testSecure = (SampleObject2)Activator.GetObject(typeof(SampleObject2), "tcp://127.0.0.1:8081/Secured.rem");
        Console.WriteLine("secure: " + testSecure.GetTest2().ToLongTimeString());
    }
    private static void Unsecure()
    {
        RegisterChannel(false, "clientUnsecure", 1);
        var test = (SampleObject)Activator.GetObject(typeof(SampleObject), "tcp://127.0.0.1:8080/Unsecured.rem");
        Console.WriteLine("unsecure: " + test.GetTest().ToLongTimeString());
    }
    internal static void MainClient()
    {
        Console.Write("Press Enter to start.");
        Console.ReadLine();
        // Works only in this order
        Unsecure();
        Secure();
        Console.WriteLine("Press ENTER to end");
        Console.ReadLine();
    }
}
static class ProgramServer
{
    private static TcpServerChannel RegisterChannel(int port, bool secure, string name)
    {
        IDictionary properties = new Hashtable();
        properties.Add("port", port);
        properties.Add("secure", secure);
        properties.Add("name", name);
        //properties.Add("impersonate", false);
        var serverChannel = new TcpServerChannel(properties, null);
        ChannelServices.RegisterChannel(serverChannel, secure);
        return serverChannel;
    }
    private static void StartUnsecure()
    {
        RegisterChannel(8080, false, "unsecure");
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(SampleObject), "Unsecured.rem", WellKnownObjectMode.Singleton);
    }
    private static void StartSecure()
    {
        RegisterChannel(8081, true, "secure");
        RemotingConfiguration.RegisterWellKnownServiceType(typeof(SampleObject2), "Secured.rem", WellKnownObjectMode.Singleton);
    }
    internal static void MainServer()
    {
        StartUnsecure();
        StartSecure();
        Console.WriteLine("Unsecure: 8080\n Secure: 8081");
        Console.WriteLine("Press the enter key to exit...");
        Console.ReadLine();
    }
}
class Program
{
    static void Main(string[] args)
    {
        if (args.Length == 1 && args[0] == "server")
            ProgramServer.MainServer();
        else
            ProgramClient.MainClient();
    }
}

Редактировать: без изменений в .NET 4 и VS 2010.

1 Ответ

1 голос
/ 08 мая 2012

Это интересный старинный вопрос, я потратил около недели, пытаясь решить эту проблему, и мне пришлось искать обходной путь. Но вот что я обнаружил: ответ, скорее всего, НЕТ, ВЫ НЕ МОЖЕТЕ.

Объяснение: .NET remoting не позволяет вам выбрать, какой клиентский канал использовать при создании объекта. На стороне сервера он будет использовать канал, слушающий рассматриваемый порт, очевидно, но на стороне клиента он просто использует любой доступный или даже создаст новый - хотя я всегда регистрирую свой собственный.

Так что кажется (я не смог найти это нигде в документации), что, если есть доступный безопасный клиентский канал, он будет использован. Таким образом, в примере в вопросе удаленный объект создается на безопасном канале, но он ожидает небезопасного - таким образом, он терпит неудачу. Если сначала создается небезопасное соединение - оно работает, потому что на момент создания удаленного объекта защищенный канал клиента отсутствует, поэтому используется небезопасный канал клиента.

ВРЕМЕННОЕ РЕШЕНИЕ:

  1. Создайте отдельный домен приложений, например, для безопасного канала.
  2. В этом AppDomain создайте объект клиента, который будет подключаться к защищенному.
  3. Используйте домен приложения по умолчанию для всех небезопасных каналов.
...