C# - TCP protokoll szinkron használata a WSE 2.0 osztályaival

forráskód letöltése
A Microsoft által elkészített és elérhetővé tett Web Services Enhancements for Microsoft® .NET (WSE) névtér 1.0-ás verziója után megjelent a 2.0 verzió, mely számtalan újdonságot tartalmaz. Többek közt lehetővé teszi, hogy a TCP protokollon keresztül kommunikáljon egymással a szerver- és a kliens-alkalmazás. Cikkünkben bemutatjuk, hogy a WSE csomag mely osztályaival valósítható meg a kommunikáció szinkron módon.
A mellékelt példa kipróbálásakor ügyeljünk az alkalmazások megfelelő sorrendben történő elindítására. Elsőként a WSServer alkalmazást indítsuk el. A mellékelt példa használatához telepítenünk kell a Microsoft WSE 2.0 csomagot. Ennek elvégzéséhez olvassa el a Kezdeti lépések című fejezetet.
Kezdeti lépések
A Microsoft által elkészített csomag a Web Services Enhancements for Microsoft .NET nevet viseli, és cikkünk írásakor a következő Webcímen volt elérhető, mely természetesen megváltozhatott:
http://www.microsoft.com/downloads/details.aspx?displaylang=en&familyid=21fb9b9a-c5f6-4c95-87b7-fc7ab49b3edd
Letöltve az állományt (WSE20TP.exe) telepítenünk kell a .NET Framework alá. Az öntelepítő állomány erről gondoskodik, a használható .DLL állomány (Microsoft.Web.Services.dll) és a kapcsolódó dokumentáció alapértelmezésben a következő mappába kerül: %winroot%:\Program Files\Microsoft WSE\v2.0\.
A telepített assembly bekerül a globális assembly-listába, így amikor referenciaként megadjuk alkalmazásainkban, akkor a globális palettáról kell kiválasztanunk, nem pedig valamilyen alternatív mappából.
Szerveralkalmazás létrehozása
A mellékelt példa két alkalmazása közül a kliensalkalmazás egy SOAP kéréssel fordul a szerverhez, elküldi a kérést egy SOAP üzenetben (borítékban), majd a választ (a szervert futtató számítógép nevét – lokális futtatás esetén a számítógépünk nevét) megjeleníti a Form-on elhelyezett szövegmezőben.
A WSServer projekt tartalmazza a szerveralkalmazás kódját. A Microsoft.Web.Services.dll assembly referenciaként történő megadása után a következő névterek hivatkozásainak elhelyezésére van szükség:
using Microsoft.Web.Services;
using Microsoft.Web.Services.Messaging;
A kommunikáció megvalósítása érdekében a szerveralkalmazásban létre kell hoznunk egy osztályt, mely a SoapService ősből származik, és létre kell hoznunk a kliens által meghívandó metódust. A metódust a SoapMethod attribútummal kell minősítenünk.
public class SServer : SoapService
{
  [SoapMethod("")]
  public string GetMachineName()
  {
    return Environment.MachineName;
  }
}
A szerveralkalmazás indulásakor megadjuk azt a virtuális URL-t, melyen a szerveralkalmazás figyelni fog.
Uri uri = new Uri("soap.tcp://" + System.Net.Dns.GetHostName() + "/SServer");
Ez a következő lesz: soap.tcp://<host számítógép neve>/SServer. A következő lépésben az URL-el azonosítva megadjuk a kérést fogadó osztály típusát.
SoapReceivers.Add(uri, typeof(SServer));
textBox1.Text = "A szerver üzemkész: " + uri;
Kliensalkalmazás elkészítése
A kliensalkalmazásban is létre kell hozni egy osztályt, melynek őse a SoapClient. Az osztályban is implementálnunk kell egy metódust, melynek neve megegyezik a szerverben található metódus nevével, de itt csak a kérést juttatjuk el a szerveralkalmazáshoz.
public class SClient : SoapClient
{
  public SClient(Uri to) : base(to){}
Az osztály konstruktorának paraméterében adjuk meg a szerver URL-jét. A metódusban az ősosztály SendRequestResponse metódusát hívjuk meg, amiben megadjuk a meghívandó metódus nevét, valamint az üzenet borítékját.
  [SoapMethod("")]
  public string GetMachineName()
  {
    return (string)base.SendRequestResponse("GetMachineName",new SoapEnvelope()).GetBodyObject(typeof(System.String));      
  }
}
A MŰVELET gomb megnyomásakor példányosítjuk a fent deklarált kliensosztályt, majd meghívjuk a metódust. A metódus eljuttatja a kérést a szerverhez, mely azonnal (szinkron módon) küldi a választ, a host nevét.
SClient proxy = new SClient(new Uri("soap.tcp://" + System.Net.Dns.GetHostName() + "/SServer"));
textBox1.Text = proxy.GetMachineName();