2010-03-30 18 views
19

Nie mogę użyć niezabezpieczonego kanału, gdy bezpieczny kanał został już zarejestrowany. Poniższy kod działa tylko wtedy, gdy po stronie klienta zarejestrowany jest niezabezpieczony kanał.Mieszanie bezpiecznych i niezabezpieczonych kanałów

Czy można mieszać bezpieczne i niezabezpieczone kanały bez żadnych ograniczeń w zamówieniu rejestracyjnym?

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(); 
    } 
} 

Edit: Bez zmian z .NET 4 i VS 2010.

+3

Mówisz, że "nie działa"; czy mógłbyś wyjaśnić, co robi? –

+0

@ M.Babcock Twój komentarz jest na bardzo stare pytanie, do korzystania, kto nie był na kilka miesięcy. Just fyi –

+0

Wiedziałem, że to dość stare pytanie, ale doszedłem do wniosku, że jest ono nadal aktualne, ponieważ moderatorzy jeszcze go nie wyłączyli. Możesz usunąć moją odpowiedź, jeśli uważasz, że nie jest to konieczne. –

Odpowiedz

1

To jest ciekawe pytanie rocznika, spędziłem około tygodnia stara się rozwiązać ten problem, i musiała wdrożyć obejście. Ale oto, co odkryłem: odpowiedź jest najprawdopodobniej: NIE, NIE MOŻESZ.

Objaśnienie: Usługa .NET nie pozwala wybrać kanału klienta, który ma być używany podczas tworzenia obiektu. Po stronie serwera używałby oczywiście kanału nasłuchującego danego portu, ale po stronie klienta używałby tylko dowolnego dostępnego lub nawet nowego - chociaż zawsze rejestrowałem swój własny.

Wygląda na to (nie mogłem znaleźć nigdzie w dokumentacji), że jeśli dostępny jest bezpieczny kanał klienta, ten zostanie użyty. Tak więc w przykładzie w pytaniu obiekt zdalny jest tworzony w stosunku do bezpiecznego kanału, ale spodziewa się, że jest niezabezpieczony - a więc zawodzi. W przypadku tworzenia niezabezpieczonego połączenia najpierw - działa, ponieważ w momencie tworzenia obiektu zdalnego nie ma bezpiecznego kanału klienta, więc używany jest niezabezpieczony kanał klienta.

Obejście:

  1. Utwórz osobny AppDomain dla, na przykład, bezpieczny kanał.
  2. W tym AppDomain utwórz obiekt klienta, który połączy się z bezpiecznym.
  3. Użyj domyślnego AppDomain dla wszystkich niezabezpieczonych kanałów.