Laden...

Remoting: Objet immer nur als neue Instanz

Erstellt von D12 vor 18 Jahren Letzter Beitrag vor 18 Jahren 3.045 Views
D
D12 Themenstarter:in
22 Beiträge seit 2005
vor 18 Jahren
Remoting: Objet immer nur als neue Instanz

Hallo Leute,

ich verzweifel langsam am Remoting!

Vorweg: Ich habe noch nie mit Remoting gearbeitet!

Anforderung:
Ein IO-Gerät wird von einem Dienst ausgelesen und die Daten sollen für eine unbestimmte Anzahl Clients ausgewertet und aufbereitet werden. Die Clients müssen die Daten direkt aus dem Arbeitsspeicher des Rechners an dem das IO-Gerät hängt lesen.

Lösungsansatz zu Testzwecken für Remoting:

class IOcounter : MarshalByRefObject
class IOserver : System.ServiceProcess.ServiceBase (Windows Dienst)
class IOconsole

Object IOcounter wird vom Windows-Dienst IOserver sauber erstellt und ein Zähler arbeitet über einen Timer.

Nun soll der Client den Zähler auslesen können und das so, das mehrere Clients darauf zugreigen können. (Threading wird mein nächstes Problem sein!)

Folgende Source macht mir Kopfzerbrechen:

RemotingConfiguration.RegisterActivatedClientType
            (typeof (IOcounter), "tcp://localhost:1234");
        IOcounter ioc = new IOcounter();

Erstellt eine neue Instanz, bei der der Zähler auf 0 steht, weil er neu deklariert und initialisiert wird.

erarbeitete Lösung aus dem .NET-Entwicklerbch von MS-Press:

IOcounter ioc = (IOcounter) Activator.GetObject(			typeof  (IOcounter), "tcp://localhost:1234/IOcounter");

Irgendwas fehlt noch!
Er kann starten, meldet aber folgenden Fehler direkt nach Start:


Unbehandelte Ausnahme: System.Runtime.Remoting.RemotingException: Angeforderter
Dienst wurde nicht gefunden

Server stack trace:
   at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(
IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders reques
tHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& respon
seHeaders, Stream& responseStream)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req
Msg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgDa
ta, Int32 type)
   at IOcounter.wert()
   at IOconsole.Main()
Drücken Sie eine beliebige Taste . . .

Nun häng ich schon seit drei Tagen mit dem Mist rum und komme nicht weiter...
Vielleicht braucht Ihr für eine Hilfe die kompletten Sourcen?
Die Sourcen habe ich --> hier <-- als *.rar verpackt!

Bin für jede sinnvolle Hilfe dankbar!

cu s00n!:
D12

Und bitte keine Antworten in denen mir mitgeteilt wird, das es Bücher gibt oder Lehrgänge. Bücher habe ich schon eine Menge und Lehrgänge war ich auch schon in vielen...

3.728 Beiträge seit 2005
vor 18 Jahren
.NET Remoting Grundlagen

zu aller erst schaust Du Dir das folgende Schulungsvideo an (Du benötigst einen Microsoft Media Player dazu):

http://www.microsoft.com/germany/msdn/nettv/folge1.mspx

Das ist nun wirklich kein Buch, vermittelt Dir aber alles was Du zunächst Wissen musst. Einfach und verständlich. Mit diesen Grundlagen solltest Du Dein Problem lösen können. Spätestens nach den folgenden Zeilen:

Dein Problem liegt an der Aktivierungsmethode. Du verwedest clientaktivierte Objekte. Das bedeutet, dass jeder Client seine eigene Instanz hat. Da Du Daten hast, die Zentral mehreren Clients zur Verfügung gestellt werden sollen, brauchst Du eine Instanz für alle Clients. Es muss deshalb ein serveraktiviertes Singleton-Objekt sein.Hier ein Beispiel:


RemotingConfiguration.RegisterWellKnownServiceType(typeof(Businesslogic.Class1), "class1.rem", WellKnownObjectMode.Singleton);

Außerdem musst Du im Host einen Namen für das Remoting-Objekt vergeben. Dieser Name muss im URL auftauchen. In meinem Beispiel wäre das "class1.rem". Am Client würde der Typ folgendermaßen erzeugt:


Businesslogic.Class1 myObject;
myObject = Activator.GetObject(typeof(Businesslogic.Class1), "tcp://localhost:8000/class1.rem");

Da alle Clients nun gleichzeitig auf EIN Objekt zugreifen, musst Du Dich in der Tat um Multithreading kümmen. Deshalb solltest Du auch noch das nun folgende Video anschauen:

http://www.microsoft.com/germany/msdn/nettv/folge7.mspx

D
D12 Themenstarter:in
22 Beiträge seit 2005
vor 18 Jahren

Hallo Rainbird,

das sieht sehr plausibel aus. Leider finde ich keinen Namespace in dem "Businesslogic" sich wohl fühlen möchte.

Welches USING brauche ich hier?

LG D12

3.728 Beiträge seit 2005
vor 18 Jahren
Beispiel

Das ist ein Beispiel. Für BusinessLogic musst Du den Typ einsetzen, der Remote verfügbar gemacht werden soll.

D
D12 Themenstarter:in
22 Beiträge seit 2005
vor 18 Jahren

Hi,

das ist plausibel, habe aber noch das Problem, das ich mit dem Object, dem Serice und dem Client durcheinander komme. Was muss da wo hin?

LG D12

3.728 Beiträge seit 2005
vor 18 Jahren
Bestandteile von Remoting

Du hast eine Klasse, die eine bestimmte Aufgabe übernimmt. Diese Klasse soll von entfernten Clients über Remoting nutzbar sein. Damit das klappt, muss die Klasse von MarshalByRefObject abgeleitet sein. Die Instanz einer Klasse nennt man Objekt (Von einer Klasse können beliebig viele (voneinander unabhängige) Objekte erzeugt werden. Nennen wir diese Klasse einfach mal Remote-Klasse. Wichtig! Die Remote-Klasse muss in einem Visual Studio Projekt vom Typ Klassenbibliothek (DLL) erstellt werden.

Da irgendwie eine Kommunikation übers Netzwerk stattfinden muss, brauchst Du noch einen Host (Manche sagen auch Server). Dieser Host ist in einem weitern Visual Studio Projekt vom Typ Konsolenanwendung oder Windows-Anwendung untergebracht. Das ist wichtig, denn der Host muss eine EXE-Datei sein (weil EXE-Dateien in einem eigenen Prozess leben). Deine Remote-Klasse darf nicht im selben Projekt sei, wie der Host. Dem Host Projekt muss die Assembly, die die Remoting-Klasse enthält, als Verweis zugefügt werden. Der Host benötigt eigentlich nur eine Main-Funktion. Dort wird die Remoting-Klasse als serveraktivierter SingleTon in der Remoting Konfiguration registriert (TcpChannel , RegisterWellKnowServiceType, ...). Damit der Host nicht sofort wieder beendet wird, lässt man ihn z.B. auf eine Tastatureingabe warten (Console.ReadLine). Wird der kompilierte Host gestartet, lauscht er auf dem angegebenen TCP/IP Port auf Clientanfragen, bis er manuell beendet wird.

Nun brauchst Du nur noch den Client. Der Client ist auf jeden Fall ein weiteres Visual Studio Projekt (z.B. eine Windows-Anwendung). Auch der Client benötigt die Assembly, die die Remoting-Klasse enthält als Verweis. Irgendwoher muss er schließblich die Schnittstelle (also welche Methoden und Eigenschaften etc. eine Klasse hat) der Remoting-Klasse kennen. Sobald die Remoting-Klasse über RemotingConfiguration als Remote-Typ konfiguriert wurden, werden alle Methodenaufrufe an Objekte dieses Typs übers Netzwerk an den Host gesendet. Dieser wartet bereits darauf, führt die entsprechende Funktion aus und sendet das Ergebnis zurück.

Wenn Du alles richtig gemacht hast, solltest Du über folgendes verfügen:*1 Bibliotheksprojekt das die Remoting-Klasse enthält *1 Konsolenanwendungsprojekt das den Host enthält *1 Windowsanwendungsprojekt das den Client enthält

Die können natürlich alle drei in der selben Projektmappe sein.

Noch Fragen?

D
D12 Themenstarter:in
22 Beiträge seit 2005
vor 18 Jahren
Remoting kann mich nicht leiden....

Hmm... Hab ich quasi alles so gemacht, einiziger Unterschied ist das ich als Host kein Konsolen-Proggy habe, sondern ein Windwos-Dienst. Er lässt mich nicht an das Objekt ran, das Einbinden funzt nicht.

Visual Studio.NET -> Hab ich nie mit gearbeitet, nicht jeder hat das Glück in einem großen Konzern zu arbeiten. Bin freischaffend, leider!

Kannst nicht mal über meinen Code drüberschauen, ich komm nicht weiter, würde sogar was dafür zahlen....

29 Beiträge seit 2005
vor 18 Jahren

Hallo Rainbird,

eine Frage an dich, warum Singleton? Und warum nicht SingleCall? Und warum TCP-Channel? Spielt dann deiner Meinung nach der Formatter keine Rolle ?
Finde deine Beiträge bissle verwirrend, da sie nicht vollständig argumentiert werden!

D
D12 Themenstarter:in
22 Beiträge seit 2005
vor 18 Jahren

Singleton weil das Object als Instanz aufgerufen wird und nicht als neue Object, so bleiben die Inhalte der Member erhalten,... Bei Single werden die Inhalte mit jeder neuen Instanz initialisiert.

29 Beiträge seit 2005
vor 18 Jahren

Das ist ein totaler Quatsch, sorry, aber der entscheidende Unterschied liegt irgendwo ganz anders!

D
D12 Themenstarter:in
22 Beiträge seit 2005
vor 18 Jahren

so stehts in den Büchern!

3.728 Beiträge seit 2005
vor 18 Jahren
Unterschied

Bei SingleCall wird für jeden Clientaufruf ein Objekt erzeugt und, die Methode ausgeführt und anschließend wieder zerstört. Es heißt SingleCall, weil das Objekt nur einen "Call" lang lebt. Singleton verwendet ein Objekt über längere Zeit für alle Clientanfragen.

Wenn ein Status zwischen den einzelnen Clientaufrufen gehalten werden muss, ist SingleCall nicht zu gebrauchen, weil der Status nach dem Aufruf sofort verlohren gehen würde.

Der Formatter ist toll, interessiert aber niemanden, der gerade damit kämpft, das ganze überhaupt zum laufen zu bringen. Warum sollte man einen HttpChannel verwenden, wenn man nicht über eine Firewall verbindet. Das ist doch nur unnötig Overhead. Binär über TCP zu übertragen ist performanter.

So siehts aus, Hase!