2010-03-30 11 views
19

Ich kann keinen unsicheren Kanal verwenden, nachdem ein sicherer Kanal bereits registriert wurde. Der folgende Code funktioniert nur, wenn auf der Client-Seite der ungesicherte Kanal zuvor registriert wurde.Mischen von sicheren und unsicheren Kanälen

Ist es möglich, sichere und unsichere Kanäle ohne Einschränkung der Registrierungsreihenfolge zu mischen?

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: Keine Änderung mit .NET 4 und VS 2010

+3

Sie sagen, dass es "nicht funktioniert"; Könntest du erklären, was es macht? –

+0

@M.Babcock Ihr Kommentar ist auf eine sehr alte Frage, zu verwenden, wer seit ein paar Monaten nicht mehr war. Nur fyi –

+0

Ich wusste, es war eine ziemlich alte Frage, aber dachte, dass es noch relevant ist, da die Moderatoren es noch nicht deaktiviert haben. Fühlen Sie sich frei, meine Antwort zu löschen, wenn Sie das Gefühl haben, dass es unnötig ist. –

Antwort

1

Diese interessante Vintage-Frage ist, habe ich etwa eine Woche lang versucht, dieses Problem zu lösen, und hatte eine Behelfslösung zu implementieren. Aber hier ist, was ich entdeckt habe: Die Antwort ist höchstwahrscheinlich: NEIN, SIE KÖNNEN NICHT.

Erläuterung: Bei .NET-Remoting können Sie nicht auswählen, welcher Clientkanal beim Erstellen eines Objekts verwendet werden soll. Auf der Serverseite würde es natürlich den Kanal verwenden, der den fraglichen Port abhört, aber auf der Client-Seite würde es nur irgendein verfügbares verwenden oder sogar ein neues erstellen - obwohl ich immer mein eigenes registriere.

So scheint es (ich konnte es nirgends in der Dokumentation finden), dass, wenn es einen sicheren Client-Kanal gibt, dieser verwendet wird. Also in Beispiel in der Frage, das Remote-Objekt wird gegen den sicheren Kanal erstellt, aber es erwartet unsicheren - so schlägt es fehl. Wenn Sie zuerst eine unsichere Verbindung erstellen, funktioniert das, weil zum Zeitpunkt der Erstellung des Remote-Objekts kein sicherer Client-Kanal vorhanden ist. Daher wird der unsichere Client-Kanal verwendet.

Abhilfe:

  1. Erstellen eines separaten Anwendungsdomäne für, zum Beispiel, sicheren Kanal.
  2. Erstellen Sie in dieser Anwendungsdomäne ein Clientobjekt, das eine Verbindung mit dem Secure herstellt.
  3. Verwenden Sie Ihre Standard-AppDomain für alle unsicheren Kanäle.