Postupem času se mění způsob tvorby aplikací z lokálních na distribuované aplikace. Zvláště se jeví praktické vytvářet aplikace jako sadu komponent distribuovaných po síti počítačů a pracovat s nimi, jako by celá sada byla umístěná na jediném počítači.
.NET Remoting přináší infrastrukturu pro distribuované objekty. Prostředí .NET Remoting nabízí komplexní funkcionalitu včetně podpory pro předávání objektů hodnotou nebo odkazem, ovládání podmínek životního cyklu apod.
Jednoduše řečeno základ Remoting tvoří používání referencí objektů ke komunikaci mezi serverem a klienty.
V zásadě je nutno dodržet následující podmínku, abychom mohli používat .NET Remoting:
Všechny vzdálené objekty musí být registrovány Remoting systémem (prostředím), než k nim může přistoupit klient.
Tato registrace se obvykle provádí před startem hostující aplikace a je ji možno provést buď s pomocí konfiguračního souboru nebo voláním registrační metody RegisterWellKnownServiceType() s patřičnými parametry. Když je objekt zaregistrován, vytvoří prostředí referenci na tento vzdálený objekt a extrahuje z assembly metadata potřebná pro lokalizaci vzdáleného objektu kdekoliv na síti.
Pokud se podaří nakonfigurovat klienta a server správně, stačí nám vytvořit novou instanci vzdáleného objektu pomocí klíčového slova new. Klient posléze získá referenci na objekt serveru a zbytek už se provádí stejně, jako by objekt byl lokální.
Na obrázku vidíme způsob, jak se pracuje se vzdálenými objekty. Pokud se vytvoří instance vzdáleného objektu, vytvoří se lokální proxy objekt jevící se klientovi stejně jako vzdálený objekt. Klient volá metodu na proxy objekt. Volání se předá Remoting Systemu, ten jej předá řídícímu procesu, vyvolá se server objekt a jeho odpověď se vrací zpět ke klientovi. Channel na obrázku reprezentuje typ, který bere proud dat, zaobalí jej v závislosti na konkrétním sítovém protokolu a odesílá jej k druhému počítači.
Pokud bychom psali Remoting System vlastnoručně, potřebovali bychom se naučit (pokud to ještě neumíme) širokou oblast protokolů a specifikací formátů pro komunikaci na síti. U .NET Remoting se o toto nemusíme starat.
Můžeme použít tyto způsoby aktivace vzdálených objektů (a s tím související způsoby vytváření instancí objektů)
Aktivace na straně serveru
Objekty na straně serveru nejsou vytvářeny při volání new na straně klienta, ale pouze tehdy, když jsou skutečně potřeba (volání metod apod.). Při volání new se pouze vytvoří proxy pro daný typ.
Jednoduché volání (Single Call)
Tyto objekty obslouží pouze jediný požadavek. Nejsou přizpůsobeny pro uchovávání stavových informací. Vždy se vytváří nová instance objektu pro každý požadavek klienta.
Jediný objekt (Singleton Object)
Tyto objekty obsluhují více klientů. Používají se v případech, kdy je třeba explicitně sdílet data mezi klienty. Nikdy se nevytváří více instancí. Pokud existuje instance objektu, všechny požadavky se směrují směrem k ní.
Aktivace klientem
Chování jako u klasických objektů. Klient vydá požadavek pomocí operátoru new a server vytvoří instanci dané třídy. Poté vyšle referenci na objekt, který byl vytvořen. Každé volání new vrací proxy k nové instanci daného typu na serveru. Pokaždé, když klient vytvoří novou instanci, se vytvoří skutečná instance na serveru a je platná do doby platnosti instance.
Použití vzdálených objektů si ukážeme na vzorovém příkladu. Jedná se o jednoduchou třídu MathLibrary s metodami pro sčítání, odčítání celých čísel a "uvítací" metody. Pokud bychom tuto třídu umístili na server (například IIS), můžeme hovořit o používání webové služby, pokud tuto třídu náležitě zpřístupníme.
Se vzdálenými třídami je možno pracovat přímo vytvořením patřičných vazeb v jazyce C# (nebo v jiném podporovaném .NET Framework) - aktivace vzdáleného objektu s pomocí třídy System.Activator na straně klienta a registrováním vzdáleného objektu pomocí metody RemotingConfiguration.RegisterWellKnownServiceType(). Lze s nimi pracovat i pomocí konfiguračních souborů, pak stačí tyto soubory načíst a může se rovnou pracovat se vzdálenými objekty. Ukážeme si druhý způsob.
Aby bylo možno pracovat s instancemi vzdálených tříd, tyto třídy musí dědit z MarshalByRefObject. Následující kód ukáže jednoduchou třídu, která může být vytvořena a volána v jiné aplikační doméně.
using System; public class MathLibrary : MarshalByRefObject { public string Invitation() { return "Hi there, this is a remote object!"; } public int Add(int num1, int num2) { return (num1+num2); } public int Sub(int num1, int num2) { return (num1-num2); } } |
Tuto třídu uložíme jako MathLibrary.cs a zkompilujeme v příkazovém řádku pomocí:
csc /noconfig /t:library MathLibrary.cs
Pokud budete mít problém se spuštěním kompilátoru a využíváte svůj vlastní počítač, csc.exe se nachází v adresáři WINDOWS\Microsoft.NET\Framework\(co nejnovější verze)\csc.exe
K tomu, abychom mohli vytvářet instance objektů na dálku, je třeba vytvořit hostitelskou aplikaci nebo naslouchací aplikaci. Tyto dělají následující dvě věci
Vybere a registruje komunikační kanál (reprezentovaný objektem, pracujícím se sítovými protokoly a formáty serializací) .
Registruje náš typ pomocí .NET Remoting system tak, aby .NET Remoting mohl využívat vytvořený komunikační kanál k naslouchání požadavků pro náš typ.
Vytvoříme tedy kód naslouchající aplikace.
using System; using System.Runtime.Remoting; public class Listener { public static void Main() { RemotingConfiguration.Configure("Listener.exe.config"); Console.WriteLine ("Listening for requests. Press Enter to exit..."); Console.ReadLine(); } } |
Předchozí kód uložíme do souboru Listener.cs a stejného adresáře jako MathLibrary.cs a opět skompilujeme, tentokrát spolu s naší knihovnou.
csc /noconfig /r:MathLibrary.dll Listener.cs
Předchozí kód ale používá k naslouchání vzdálených typů soubor Listener.exe.config, je zapotřebí vytvořit i tento konfigurační soubor. V něm nastavíme, jak se bude s naším typem zacházet, způsob komunikace apod. Uložíme jej opět do stejného adresáře.
<configuration> <system.runtime.remoting> <application> <service> <wellknown mode="Singleton" type="MathLibrary, MathLibrary" objectUri="MathLibrary.rem" /> </service> <channels> <channel ref="http" port="8989"/> </channels> </application> </system.runtime.remoting> </configuration> |
V této chvíli máme vytvořenou knihovnu s matematickými funkcemi a hostitelskou aplikaci pro vzdálené používání (Remoting).
Nyní vytvoříme klientskou aplikaci. Ta se musí zaregistrovat jako klient pro vzdálený objekt. Pak při volání instance vzdálené třídy .NET Remoting zachytí zprávy klienta a předá je vzdálenému objektu. Následně vrátí klientu výsledek.
using System; using System.Runtime.Remoting; public class Client { public static void Main() { string strNum1, strNum2; int num1, num2; RemotingConfiguration.Configure("Client.exe.config"); MathLibrary lib = new MathLibrary(); Console.WriteLine("Enter number 1:"); strNum1 = Console.ReadLine(); Console.WriteLine("Enter number 2:"); strNum2 = Console.ReadLine(); num1 = Convert.ToInt16(strNum1); num2 = Convert.ToInt16(strNum2); Console.WriteLine("Addition {0} + {1} = {2}", num1, num2, lib.Add(num1, num2)); } } |
Výše uvedený kód uložíme jako Client.cs do stejného adresáře jako předchozí a opět skompilujeme s knihovnou MathLibrary
csc /noconfig /r:MathLibrary.dll Client.cs
Jelikož ale klient opět používá konfigurační soubor Client.exe.config k naslouchání vzdáleného typu, je třeba ještě vytvořit tento soubor. Umístíme jej opět do stejného adresáře jako všechny předchozí.
<configuration> <system.runtime.remoting> <application> <client> <wellknown type="MathLibrary, MathLibrary" url="http://localhost:8989/MathLibrary.rem" /> </client> </application> </system.runtime.remoting> </configuration> |
Nyní nám už nic nebrání spuštění námi vytvořené aplikace. Je třeba mít na paměti, že po celou dobu volání klientů musí být spuštěno naslouchání - Listener.exe.
Spustíme tedy Listener.exe, následně spouštíme Client.exe a vidíme výsledek.
Tento příklad je k dispozici ke stažení ve formátu zip zde. |