Download as pdf or txt
Download as pdf or txt
You are on page 1of 22

DISTRIBUIRANI UPRAVLJAKI SISTEMI

Osnove C# jezika i WCF-a


-SKRIPTA-

Novi Sad Decembar, 2008

C# i .Net Framework
.NET Framework je dizajniran kao integrisano okruenje razvoj aplikacija za Internet, desktop Windows Forms aplikacije, kao i za mobilne ureaje (pomou Compact Framework).Osnovne ideje pri dizajniranju su bile:

Da se formira konzistentno objektno orijentisano okruenje za razliite aplikacije. Da se napravi okruenje koje minimizuje probleme za uvoenjem novih verzija programa ("DLL Hell") koji su postojali u Windows (COM) okruenju, i da se pojednostavi proces distribucije/instalacije. Da se formira portabilno okruenje, bazirano na opteprihvaenim standardima, koje moe da se izvrava na proizvoljnom operativnom sistemu. Da se obezbedi upravljano (managed) okruenje u kome e se kod lako i sigurno izvravati.

Da bi se ostvarili ovi ciljevi, .NET Framework je oslonjen na arhitekturu koja deli framework ba dva dele: Common Language Runtime (CLR) i Framework Class Library (FCL). Slika 1. prikazuje tu podelu. CLR vodi rauna o izvravanju koda i svim ostalim zadacima u vezi sa tim: kompajliranje, upravljanje memorijom, sigurnost, upravljanje nitima, i kontrolie tipove podataka. Kod koji se izvrava u CLR se naziva upravljani (managed) kod. Nasuprot tome, neupravljni (unmanaged) je kod koji ne implementira zahteve za rad u .Net framework-u kao to je COM ili Windows API . Druga komponenta, Framework Class Library, predstavlja biblioteku klasa i struktura koje su na raspolaganju aplikacijama koje rade u .NET. Tu spadaju klase za pristup bazama podataka, grafiki intefejs, interoperabilnost sa neupravljanim kodom, sigurnost podataka, kao i za Web i Windows forme. Svi programski jezici prilagoeni .NET-u koriste ovu bibilioteku. Slika 1. Osnovne komponente .Net Framework-a

Common Language Runtime


Common Language Runtime upravlja celim ivotnim vekom aplikacije: on pronalazi kod, prevodi ga, uitava potrebne klase, upravlja njihovim izvravanjem, i osigurava automatsko oslobaanje memorije. CLR je zaduen i za integraciju koda izmeu razliitih programskih jezika.

Prevoenje .NET Code


Programski prevodioci koji su kompatiblini sa CLR-on proizvode kod koji je pogodan za izvravanje u runtime-u, za razliku od onih proizvedenih za specifini CPU. Ovaj kod, poznat pod razliitim imenima Common Intermediate Language (CIL), Intermediate Language (IL), ili Microsoft Intermediate Language (MSIL), je asemblerski jezik koji se pakuje u EXE ili DLL datoteke. Ovaj kod (intermediate code) je kljuna stvar za ispunjenje osnovnog cilja .NET Framework-a ineroperabilnost izmeu programskih jezika.Slika 2 ilustruje na koji nain Common Language Runtime nemora da zna, niti treba da zna, u kom programskom jeziku je aplikacija napisana. CLR komunicija sa jeziki nezavisnim IL. Zahvaljujui tome to aplikacije komuniciraju kroz IL, izlaz iz jednog prevodioca moe moe biti integrisano sa kodom koji je proizveo drugaiji prevodilac.
Slika 2. Mesto i funkcija CLR-a

Konsturkcija C# Programa
Na slici 3 su prikazani osnovni elementi C# programa Slika 3. Osnovni elementi C# programa

Kod sa slike 3. se sastoji od klase MyApp koja poseduje programsku logiku i klasu Apparel koja sadri podatke. U programu se formira instanca Apparel i dodeljuje se promenivoj myApparel. Ovaj program se dalje koristi da bi se ispisala vrednost promenjive FabType i Price na ekran. Bitni delovi ovog programa su: 1. using naredba definie supove klasa (namespace) System. U ovom programu se koriste samo osnovni namespace System u kome se nalaze osnovni tipovi podataka. using naredba govori prevodiocu gde da gleda kada trai koriene tipove podataka, ime je omogueno da nije potrebno pisati puno ime klase. Naprimer, mogue je samo napisati Label umesto System.Web.UI.WebControls.Label. 2. Sva programska logika i podaci moraju biti ubaeni u: klase, strukture, enumeracije, intefejse ili delegate. Za razliku od Visual Basic-a, C# nema globalne promenjive koje bi postojale van navedenih tipova podataka. Pristup tipovima i njihovim podacima je striktno kontrolisano. U navedenom primeru public omoguuje da druge klase kao to je MyApppristupe lanicama Apparel klase. 3. Main() method je obavezan za svaku izvrnu C# aplikaciju. Ovaj metod slui kao ulazna taka za aplikaciju; ona uvek mora biti static i slovo M mora biti veliko. Mogue je definisane i verzije Main()koje imaju ulazne parametre i/ili povratne vrednosti.

Tipovi podataka i kontrola toka programa


Osnovni tipovi podataka (primitives), kao to im i samo ime kae, predstavljaju jezgro C# tipova podataka. Slue kao gradivni blokovi za kompleksnije tipove klasa i struktura. Promenjive ovog tipa sadre jednu vrednost i uvek imaju istu predefinisanu veliinu..U tabeli 1. je data lista osnovnih tipova podatak, odgovarajui FLC tipovi podataka, i veliine memorije koju zauzimaju.

Tabela 1. Osnovni tipovi podata


C# tipovi
object string decimal bool char byte sbyte short int long ushort uint ulong

FCL typovi
System.Object System.String System.Decimal System.Boolean System.Char System.Byte System.SByte System.Int16 System.Int32 System.Int64 System.UInt16 System.UInt32 System.UIint64

Description Osnovna klasa za sve dugi tipovi. Sekvenca Unicode karaktera. Precizan decimalni broj sa 28 cifara. Vrenosti true ili false. 16-bit Unicode karakter. 8-bit neoznaeni celobrojni tip. 8-bit oznaeni celobrojni tip. 16-bit oznaeni celobrojni tip. 32-bit oznaeni celobrojni tip. 64-bit oznaeni celobrojni tip. 16-bit neoznaeni celobrojni tip. 32-bit neoznaeni celobrojni tip. 64-bit neoznaeni celobrojni tip. Jenostruka preciznost sa pokretnim zarezom. Dvostruka preciznost sa pokretnim zarezom.

single (float) System.Single double System.Double

Kontrola toka programa


Kontrola programa u C# je vrlo slina kontroli programa u Javi ili C++. Tabela 2. prikazuje definiciju i primere za uslovno grananje i case sturturu.

Tabela 1. Kontrola toka programa


Uslovne komande
if (boolean expression) { // statements } else { // statements }

Primer
if (bmi < 24.9) { weight = "normal"; riskFactor = 2; } else { weight = "over"; riskFactor=6; }

switch (expression) { case constant expression: // statements; // break/goto/return() case constant expression: // statements; // break/goto/return() default: // statements; // break/goto/return() }

switch (ndx) { case 1: fabric = "cotton"; blend = "100%"; break; case 2: // combine 2 & 3 case 3: fabric = "cotton"; blend = "60%"; break; default: // optional fabric = "cotton"; blend = "50%"; break; }

Petlje
U C# postoje etiri vrste petlji: while, do, for, i foreach, koje takoe imaju slinu strukturu kao i u Javi ili C++. U tabeli 2. su prikazani definicije i primeri ovih naredbi. Deifnicija
while ( boolean expression ) { body }

Primer
byte[] r = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF}; int ndx=0; int totVal = 0; while (ndx <=6) { totVal += r[ndx]; ndx += 1; } byte[] r = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF}; int ndx=0; int totVal = 0; do { totVal += r[ndx]; ndx += 1; }while (ndx <= 6); int[] r = {80, 88, 90, 72, 68, 94, 83}; int totVal = 0; for (int ndx = 0; ndx <= 6; ndx++) { totVal += r[ndx]; } int totVal = 0; foreach (int arrayVal in r) { totVal += arrayVal; }

do { do-body } while ( boolean expression );

for ( [initialization]; [termination condition]; [iteration] ) { for-body } foreach ( type identifier in collection ) { body }

Klase u C#
Definicija klase u C# ima sledee elemente: 1. Atributi su opcionalni elementi koji dodatno opisuju klasu (recimo ClassDesc, Serialiazable) 2. U Deklaraciji klase se definisu prava pristupa kao i ime klase 3. U klasi je mogue definisati lokalne konstante i osobine 4. Konstruktor slui za inicijalizaciju klase. Moe postojati vie konstruktora sa razliitim ulaznim parametrima, ali konstruktor nikada ne vraa vrednost. 5. Momou Property-a se mogu kontrolisati prava pristupa osobinama klase 6. Metode predstavljaju funkcije koje se mogu pozvati nad objetkom klase
Slika 4. Elementi klase u C#

Interfejsi Interfejsi predstavljaju skup metoda koje neka klasa treba da implementira. Interfejs se definie pomou kljune rei interface
[attributes] [modifiers] interface {interface body} [;] identifier [:baselist]

Generics Generics, predstavlja novi concept uveden u.NET 2.0, i nudi eleganto reenje koje eliminie kastvovanje tipa, proveru tipa, i pakovanje (boxing) koje se koristi kada se pritivni tipovi prebacuju u object.

Kolekcije u .Net-u
U .NET-u, kolekcija je zajedniko ime za skup klasa koje predstavljaju klasine structure podataka koje se koriste za grupisanje srodnih podataka. Tu spadaju stacks, queue, hash table, array, i dictionary. Sve one su definisane u dva namespace-a: System.Collections i System.Collections.Generic. u .NET verzijama 1.0 i 1.1, postoji samo System.Collections. Sa pojavom .NET 2.0, originalne kolekcije su promenjene tako da podravaju generics. Tabele 3. Interfejsi za kolekcije Interface Opis
ICollection

Osnovni interfejs za sve klase. Sadri osobinu Count koja govori koliko ima elementa u kolekciji.Takoe poseduje metodu za kopiranje kolekcije u niz (CopyTo). Definie metodu koja slui za poreenje dva elementa u kolekciji (CompareTo) to je kljuno za sortiranje kolekcije. Omoguuje da se objekti predstavljaju u obliku key -value parova. Omoguuje prolazak kroz kolekciju koja definie IDictionary tako to omoguuje prolaz kroz klueve i vrednsoti Definie metode za jednostavnu iteraciju kroz kolekiciju. Pomou iteratora je mogue jedino oitavanje elemenata kolekcije. Tu spadaju metode
GetEnumerator, Current, MoveNext, Reset

IComparer

IDictionary IDictionaryEnumerator

IEnumerator IEnumerable

IHashCodeProvider IList

Definie hashCode za svaki objekak u kolekciji. Poseduje jednu methodu:


GetHashCode(object obj)

Osnovni interfejs za sve list. Kontrolie da li elementi liste mogu izmenjeni, dodati, ili obrisani

Po tome koje interfejse podrzavaju mogu se razlikovati tri podrvste kolekcija sto je prikazano na slici 5
Slika 5. Kolekcije u C#

Sa uvodjenjem Generics u .Net formirane su i odgovarajue kolekcije, a njihov uporedni spisak je dat u tabeli 4 Tabela 4. Uporeni prikaz kolekcija sa i bez generics klasa System.Collections System.Collections.Generic
Comparer Hashtable ArrayList Queue SortedList Stack ICollection IComparable IComparer IDictionary IEnumerable IEnumerator IKeyComparer IList Comparer<T> Dictionary<K,T> List<T> Queue<T> SortedDictionary<K,T> Stack<T> ICollection<T> IComparable<T> IComparer<T> IDictionary<K,T> IEnumerable<T> IEnumerator<T> IKeyComparer<T> IList<T> LinkedList<T>

(not applicable)

ZADATAK: Formirati ArrayList i u njega ubaciti million promenjivih tipa int, zatim formirati List<int> i u nju ubaciti isti broj elemenata. Uporediti vremena izvravanja ova dva postupka.
ArrayList a1 = new ArrayList(); Stopwatch stop = new Stopwatch(); stop.Start(); Trace.WriteLine(stop.ElapsedMilliseconds.ToString()); int max = 10000000; for (int i = 0; i < max; i++) a1.Add(i); Trace.WriteLine(stop.ElapsedMilliseconds.ToString()); List<int> a2 = new List<int>(); for (int i = 0; i < max; i++) a2.Add(i); Trace.WriteLine(stop.ElapsedMilliseconds.ToString());

Delegati i Dogaaji
Klik na dugme, pokretanje mia preko forme, pritisak na Enter dugme, karakter primljen sa I/O portasve su ovo okidai (trigger) koji obino pozivaju jedan ili vie poziva programskih rutinama za obradu dogaaja. U .NET svetu dogaaji su lanice klase isto kao i osobine i metode. Sve klase iz .Net Framework biblioteke klasa imaju dogaaje. Osnovni primer je Control klasa, koja slui kao osnovna klasa za sve GUI komponente. Ova klasa ima dogaajeClick, DoubleClick, KeyUp, i GotFocus koji su dizajnirani da prepoznaju najee akcije koje se dogaaju u interakciji korisnikog interfejsa i programa. Sad duge strane je potrebno definisati metode koje su odgovorne da odreaguju na dogaaje. Ove metode se zovu obraivai dogaaja (event hander). Slika 6. Odnos izmeu dogaaja i obraivaa dogaaja

Delegati
Delegati povezuju dogaaje i obraivae dogaaja. Ovaj objekat odrava listu metoda koje treba pozvati kada se desi dogaaj. C# kompajler vri proveru da bi obezbedio da delegat poziva samo metode koje imaju ulazne parameter i povratne vrednosti koje su specificirane u opisu delegata.Kao primer moemo pogedati delegate koji im sledeu definiciju: public delegate void AlarmUProcesu (int type, string msg); Kada se delegat definie, C# kompajler pravi sealed klasu koja ima ime kao i delegat (AlarmUProcesu). U klasi je definisan konstuktor koji prima parameter ime metode. Ta klasa sadri metode koje omoguuju delegatu da odrava listu metoda koju treba pozvati. Metoda mora biti registrovan kod delegate da bi ga delegat pozvao. Samo metode koje nemaju povratnu vrednost i primaju dva parametra (int i string) mogu biti registrovane kod delegata; u suprotnom e biti prijavljena greska pri prevoenju. Listing 1. prikazuje kako se definie AlarmUProcesu delegat i kako se registuje vie metoda za njega. Kada neko pozove delegata, on proe
kroz svoju internu listu za pozive, i pozove regisrovane metode redosledom kojim su registrovani. .

Listing 1. Deklaracija delegate i poziv dogaaja


// file: delegate.cs using System; using System.Threading; class DelegateSample { public delegate void AlarmUProcesu(int type, string msg); public static void OdstamajAlarm(int t, string s)

{ Console.WriteLine("Alarm odstampan-tip:"+ t.ToString()+ " sa porukom: "+s ); } public static void DodajAlarmULog(int t, string s) { // dodati kod za upis u bazu Console.WriteLine("Alarm upisan u bazu:" + t.ToString()+" sa porukom: "+ s); } public static void Main() { AlarmUProcesu myDel; // register method to be called by delegate myDel = new AlarmUProcesu(OdstamajAlarm); // register second method myDel += new AlarmUProcesu(DodajAlarmULog); // call delegate myDel(1, "Kvar na motoru 1 u pogonu 2"); } }

Treba primetiti da se operator += koristi za dodavanje metode u listu pozivanja. Nasuprot tome metod moe biti izbrisan iz te liste pomou operatora -=
myDel += new AlarmUProcesu (OdstamajAlarm); // dodaje metod u listu myDel -= new AlarmUProcesu (OdstamajAlarm); // uklanja metod iz liste

ZADATAK: Formirati klasu Item koja ima tri osobine: Value tipa double, TimeStamp tipa DateTime i Quality tipa int. Zatim formirati klasu Server koja sadri mapu Dictionary<int,Value> u koju se smetaju vrednosti nekih veliina. Server treba da ima dve metode Write koja ima dva ulazna parametra id veliine i Item, i metodu Read koja ima ulaznu vrednost int, a vraa Item.
public class Item { public double Value; public DateTime TimeStamp; public int Quality; public Item(double v, DateTime t, int q) { Value = v; TimeStamp = t; Quality = q; } }; public class Server { private Dictionary<int, Item> items = new Dictionary<int, Item>(); public void Write(int id, Item item) { items[id] = item; } public Item Read(int id) { return items[id]; } }; static void Main(){ { Server s = new Server();

s.Write(1, new Item(1.2, DateTime.Now, 1)); s.Write(2, new Item(4.4, DateTime.Now, 0)); int id = 1; Item i = s.Read(id); Console.WriteLine(@"Vrednost ocitana: id = {0}, Vrednost = {1}, vreme = {2}, kvalitet ={3} ", id, i.Value, i.TimeStamp, i.Quality); }

Dodatni zadaci: 1. Proiriti program tako da server podrava motodu Clear koja brie sve veliine iz mape 2. Uvesti proveru da li ima elemenata u mapi pri pozivu metode Read

Windows Communication Foundation


Windows Communication Foundation, ili WCF, je programsko okruenje (deo .Net Framework-a) koje slui za meuprocesnu komunikaciju. Originalno je ovaj projekat bio poznat po imenu "Indigo", a predstavlja jedan od etiri novih API-a koji su uvideni u .Net 3.0 koji su objavljeni Decembra 2006. Ideja WCF-a je da ujedini razliite komunikacijone programske modele koji su postojale u .NET 2.0, u jedinstven model. .NET 2.0 je posedovao razliite API-e za SOAP-baziranu komunikaciju (Web servise), binarni API za komunikaciju izmeu aplikacija koje su pokrenuti na Windows plaftormama (.Net Remoting), transakcionu komunikaciju (Distributed Transactions), i asinhrone komunikacije (Message Queue).

WCF Service
WCF Service se sastoji iz tri dela Servis koja implemntira metode koje e biti pozivane, host u kom e se servis izvravati, i jednu ili vie taaka pristupa (endpoints) na koje e se klijenti povezivati. Sva komunikacija u WCF-u se deava kroz take pristupa. U taki pristupa je definisan ugovor (Contract) koji definie metode servisa kojima klijent moe pristupati. Druga bitna stvar koja se defiie je nain povezivanja (binding) koji specificira tip komunikacionog kanala koji e biti korien. Trei deo endpint-a je adresa na kojoj e servis biti postavljen

Tabela 5.Tipovi povezivanja u WCF-u


BasicHttpBinding - Osnovni HTTP nain kominikacije koji obezbeuje maksimalnu interoperabilnost, a zasnovan je na WS-BasicProfile 1.1 WSHttpBinding napredniji HTTP zasnovan na WS-* protocols WSDualHttpBinding - Dupleks HTTP komunikacija, server otvara dugi kanal kroz koji moe pozivati metode na klijentu. WSFederationBinding - HTTP komunikacija u kojoj se pristup podacima moe biti kontrolisan preko prava pristupa koje dodeljuje specifian odgan za dodelu sertifikata NetTcpBinding Sigurana, pouzdana, komuikacija visokih performansi zasnovana na TCP protokolu i binarnim porkukama. NetNamedPipeBinding Sigurna, pouzdana, komunikacija visokih performansi izmeu WCF aplikacija koje su pokrenute na istom raunaru NetMsmqBinding Komunikacija izmeu WCF aplikacija kojas se zasniva na Microsoft Message Queuing (MSMQ) serveru MsmqIntegrationBinding - Komunikacija izmeu WCF aplikacija i ostalih aplikacija preko MSMQ NetPeerTcpBinding Komunikacija izmeu WCF aplikacija preko Windows Peer-to-Peer mrea.

Sinhrona komunikacija pomou WCF-a (Veba 2)


U narednom primeru bie opisan nain pravljenja command promt klijenta i servera. U VS 2008 okruenju izabrati File-> New project, pa u otvorenom dijalogu Visual C# i za tip projekta Console Application. Prvo se formira klasa ServerWCF.
// File: ServerWCF.cs using System; sealed class ServerWCF { static void Main(){ } }

Ugovor
Zatim je potrebno definisati ugovor (contract) IWCFServer koji ima dve operacije: Write koji upisuje double vrednost u promenjivu definisanu sa id-om. Druga funkcija, Read oitava vrednost veliine sa datim id-om.
// File: ServerWCF.cs [ServiceContract] public interface IWCFServer { [OperationContract] void Write(int id, doulbe input); [OperationContract] doulbe Write(int id); }

Definisanje Adrese i naina povezivanja (Binding)


Posle definisanja ugovora potrebno je rei gde server treba da slua dolazece poruke i u kom formatu e te poruke doi. Za to slue adresa System.Uri tipa, i nain povezivanja System.ServiceModel.Channels.Binding ili neki drugi izvedeni tip.
// File: ServerWCF.cs static void Main(){ // definise gde ce servis slusati Uri address = new Uri("http://localhost:8000/IServiceWCF"); // definisanje nacina povezivanja BasicHttpBinding binding = new BasicHttpBinding(); }

U navedenom primeru je definisano da e servis biti dosutpan pomou HTTP transportnog protokola na adresi http://localhost:8000/IServiceWCF

Formairanje take pristupa (Endpoint)


Sledee sto je potrebno formirati je taka pristupa (Endpoint) ona se satoji od: adrese, binding-a, i contract -a. Svaki WCF moe da ima vie endpoint-a. Klasa System.ServiceModel.ServiceHost slui za pravljenje taaka pristupa i takoe uva sve napravljene endpoint-e i omoguuje pristup serveru. Sledei primer formira taku pristupa za ServerWCF i otvara ga za sluanje na portu 4000, zatim obavetava korisnika da je server podignut i eka na pritisak na tastaturu za zavretak programa.
using System; using System.ServiceModel; using System.ServiceModel.Channels; sealed class WCFServer : IWCFServer { // indicate when a WCFServer object is created WCFServer() { Console.WriteLine("WCFServer object created"); } static void Main(){ // define where to listen for messages Uri address = new Uri("http://localhost:4000/IWCFServer"); // define how to exchange messages BasicHttpBinding binding = new BasicHttpBinding(); // instantiate a ServiceHost, passing the type to instantiate // when the application receives a message ServiceHost svc = new ServiceHost(typeof(WCFServer)); // add an endpoint, passing the address, binding, and contract svc.AddServiceEndpoint(typeof(IWCFServer), binding, address); // begin listening svc.Open(); // indicate that the receiving application is ready and // keep the application from exiting immediately Console.WriteLine("WCFServer spreman za prinanje poruka"); // wait for incoming messages Console.ReadLine(); // close the service host svc.Close(); } static Hashtable items = new Hashtable(); // received messages are dispatched to this instance // method as per the service contract public void Write(int id, double input) { items[id] = input; Console.WriteLine("Vrednost upisana {0} = {1} the body contains: {0}", id.ToString(), input.ToString()); } public double Read(int id) { double value = -1; if (items.ContainsKey(id)) { Console.WriteLine("Vrednost ocitana {0} = {1} the body contains: {0}", id.ToString(), value.ToString()); value = (double)items[id]; }

return value; } } [ServiceContract] public interface IWCFServer { [OperationContract] void Write(int id, double input); [OperationContract] double Read(int id); }

WCF klijentska aplikacija


Sa klijentske strane su isti gradivni elementi potrebni kako bi se ostvarila komunikacija sa serverom: address, binding, i contract i oni se formiraju na slian nain kao i na servrskoj strani. Klijentsku aplikaciju formirati kao novu konzolnu applikaciju.
// File: HelloWCFApp.cs using System; using System.ServiceModel; using System.ServiceModel.Channels; sealed class ClientWCF { // indicate when a ClientWCF object is created ClientWCF() { Console.WriteLine("ClientWCF object created"); } static void Main() { // define where to listen for messages Uri address = new Uri("http://localhost:4000/IWCFServer"); // define how to exchange messages BasicHttpBinding binding = new BasicHttpBinding(); // begin the sender code // create a channelFactory<T> with binding and address ChannelFactory<IWCFServer> factory = new ChannelFactory<IWCFServer>(binding, new EndpointAddress(address)); // use the factory to create a proxy IWCFServer proxy = factory.CreateChannel(); // use the proxy to send a message to the receiver int id = 1; double writeValue = 100.4; double readValue; proxy.Write(id, writeValue); Console.WriteLine("Vrednost upisana {0} = {1}", id.ToString(), writeValue.ToString()); readValue = proxy.Read(id); Console.WriteLine("Vrednost ocitana {0} = {1}", id.ToString(), readValue.ToString()); Console.ReadLine(); } }

[ServiceContract] public interface IWCFServer { [OperationContract] void Write(int id, double input); [OperationContract] double Read(int id); }

Analiza formata poruke (Message)


WCF omoguuje lako oitavanje sadraja poruke koja je razmenjena izmedju klijenta i servera. To se ini pomou klase OperationContext.Current.RequestContext.RequestMessage, tako da sada Write metoda izgleda ovako:
public void Write(int id, double input) { items[id] = input; Console.WriteLine("Vrednost upisana {0} = {1}", id.ToString(), input.ToString()); Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage.ToString( )); }

Sada izlaz serverske aplikacije po pozivu Write metode izgleda:


WCFServer spreman za prinanje poruka WCFServer object created Vrednost upisana 1 = 100.4 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addr essing/none">http://localhost:4000/IWCFServer</To> <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/ addressing/none">http://tempuri.org/IWCFServer/Write</Action> </s:Header> <s:Body> <Write xmlns="http://tempuri.org/"> <id>1</id> <input>100.4</input> </Write> </s:Body> </s:Envelope> WCFServer object created Vrednost ocitana 1 = 100.4

Mala promena sa velikim posledicama


WCF infrastruktura je zaduena za ceo proces razmene poruka, zato je promena formata poruka veoma jednostavna iz perspektive programera. Ako samo promenimo jedan red i u klijentu i u serveru koji definise nain povezivanja. Razmenjene poruke e imati potpuno drugaiji format. Recimo zameniemo:

BasicHttpBinding binding = new BasicHttpBinding();

sa:
WSHttpBinding binding = new WSHttpBinding();

Proveriti kakvav format poruke e biti prikazan u serverskoj aplikaciji posle poziva Write metode u ovom sluaju.

Upotreba metapodataka (Metadata)


U prvom primeru smo krenuli od injenice da i server i klijent poznaju Contract IWCFServer. Mada ovo u optem sluaju nije nemogue uvodi ogranienje da se i klijenti moraju menjati svaki put kada se desi minimalna promena Contract-a. WS-MetadataExchange specifikacija opisuje kako server moe da objavi format podataka koji se razmenjuje. Po default-u WCF ne objavljuje metapodatke. Ako je potrebno mogue je formirati endpoint koji slui specifino za razmenu metapodataka. Prvi korak za pravljenje endpoint-a za metapodatke je da se izmeni ServiceHost tako da prua metapodake. To se radi tako to se objekta System.ServiceModel. Description.ServiceMetadataBehavior doda u behavior kolekciju u ServiceHost. Behavior je specifina informacija koju WCF koristi da izmeni procesiranje lokalnih poruka. Sledei primer prikazuje kako se dodaje ServiceMetadataBehavior objekat u aktivni ServiceHost:
// instantiate a ServiceHost, passing the type to instantiate // when the application receives a message ServiceHost svc = new ServiceHost(typeof(WCFServer), address); // BEGIN NEW METADATA CODE // create a ServiceMetadataBehavior ServiceMetadataBehavior metadata = new ServiceMetadataBehavior(); metadata.HttpGetEnabled = true; // add it to the servicehost description svc.Description.Behaviors.Add(metadata);

Sledei korak je da se definie Binding za endpoint za metapodakte, zatim se formira metapodatke, i na kraju se endpoint doda u ServiceHost.
// instantiate a ServiceHost, passing the type to instantiate // when the application receives a message ServiceHost svc = new ServiceHost(typeof(HelloWCF)); // BEGIN NEW METADATA CODE // create a ServiceMetadataBehavior ServiceMetadataBehavior metadata = new ServiceMetadataBehavior(); // add it to the servicehost description svc.Description.Behaviors.Add(metadata); // create a TCP metadata binding Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); // create an address to listen on WS-Metadata exchange traffic

URI za

Uri mexAddress = new Uri("net.tcp://localhost:5000/IHelloWCF/Mex"); // add the metadata endpoint svc.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexAddress); // END METADATA CODE

Klijentska aplikacija sa Metapodacima


Microsoft .NET Framework SDK instalira i program svcutil.exe, koji moe da pita pokrenutu aplikaciju za poruke koje razmenjuje i na osnovu toga generie proxy. svcutil.exe koristi WSMetadataExchange protokol, kao i WSDL get semantiku.

Generisanje Proxy sa Svcutil.exe


Pre nego to se pokrene svcutil.exe, treba proveriti da je WCFServer.exe pokrenut. Nakon toga se pokrene Windows SDK Command Prompt i pokrene sledea komanda:
C:\temp>svcutil /target:code net.tcp://localhost:5000/IWCFServer/Mex

Svcutil.exe e napraviti: WCFServer.cs i output.config. Kada se pogleda WCFServer.cs moe se videti da je napravljen izvorni kod za IWCFServer inteface, intefejs IWCFServerChannel i tip WCFServerClient. Moe se primetiti da u WCFServer.cs nema podatka o adresi servera. Ta informacija se nalazi u drugoj datoteci generisanoj pomou svcutil.exe (output.config). Da bi pokazali kako se koriste generisane datoteke formiraemo novog konzolnog klijenta za WCFServer (WCFSender). Prvo je potrebno preimenovati output.config datoteku tako da postane config za novog klijenta (proneni output.config u app.config).

Izvorni kod za WCFSender with Svcutil.exe-Generated Types


Prvo je potrebno napraviti novi projekat (Console Application) po imenu WCFSender. U projekat ubaciti app.config I WCFServer.cs dobijene od svcutil.exe

using System; using System.ServiceModel; sealed class WCFSender { static void Main(){ // print to the console that we are sending a message Console.WriteLine("Pocetak pozivanja service-a"); // create the WCFServerClient type created by svcutil WCFServerClient proxy = new WCFServerClient(); // invoke the Say method proxy.Write(2, 11.22); proxy.Close(); // print to the console that we have sent a message Console.WriteLine("Poruka poslana serveru "); Console.ReadLine(); } }

Pokrenuti WCFServer klijentsku aplikaciju i proveriti da li vrednost mogue oitati iz drugog klijenta ZADACI ZA SAMOSTALAN RAD: 1. Promeniti WCFServer tako da podrava vie ServiceEndpoint-a 2. Proveriti performase komunicije Pomou (slati veliki broj poruka)

Jednosmerne metode (Veba 3)


Kada operacija nema povratnu vrednost, i kada klijentu nije vano da li je poziv uspeo ili nije mogu se koristiti One-Way operacije. Kada klijent uputi poziv WCF generie upit (request), ali se odgovarajui odgovor nee nikada generisati. Bitno je napomenuti da eventuali izuzetci (exception) koji se dogode na serveru nee stii do klijenta. U idealnom sluaju kada klijent pozove one-way metodu, on treba da bude blokiran samo kratko vreme potrebno da se uputi poziv. U stvarnosti, one-way nisu isto to i asinhroni pozivi. Kada one-way pozivi stignu do servisa, mozda nee biti obraeni odmah, mogu biti stavljeni u red ekanja na strani servisa. Koliko poruka (bili one-way ili request-reply) the servis moe da ubaci u red ekanja zavisi od konfiguraciji kanala. Ako broj poruka u redu ekanja prevazilazi kapacitet reda, klijent e biti blokiran, iako je u pitanju one-way poziv. Sa druge strane, ako je poziv primljen bez reda ekanja (to je najei sluaj), klijent je osloboen i moe da nastavi sa izvravanjem, dok servis procesira poziv u pozadini. Svi WCF binding podravaju one-way operacije.

Konfigurisanje jednosmerni operacija


OperationContract

atribut ima Boolean IsOneWay:

[AttributeUsage(AttributeTargets.Method)] public sealed class OperationContractAttribute : Attribute { public bool IsOneWay {get;set;} } IsOneWay IsOneWay

ima podrazumevanu vrednost = false, to znai da operacija nije jednosmerna. Ako se postavi na True ta operacija postaje jednosmerna:

[ServiceContract] interface IMyContract { [OperationContract(IsOneWay = true)] void MyMethod( ); }

Zadatak: proiriti postojei interface IWCFServer sa dodatnom meodom StartBackupData koja je jednosmerna. Zatim u implementaciji servera dodati tu metodu tako da u njoj server eka (pomou Thread.Sleep metode) 5 sekundi kako bi simulirao operaciju koja dugo traje (recimo pisanje na disk velike koliine podataka) i proveriti da li je klijent blokiran za vreme izvravanja operacije na serveru.

public interface IWCFServer { //ovo je dodatna metoda potrebno je sacuvati postojece [OperationContract(IsOneWay = true)] void StartBackupData(string path); } sealed class WCFServer : IWCFServer { //ovo je dodatna metoda potrebno je sacuvati postojece public void StartBackupData(string path) { System.Threading.Thread.Sleep(5000); } }

You might also like