https://www.buraksenyurt.com/Burak Selim Şenyurt - .Net Remoting2017-01-24T14:45:39+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/-Net-Remoting-Dunyasc4b1ndan-WCFe-Gecmek-bsenyurt-com-dan.Net Remoting Dünyasından WCF'e Geçmek2007-12-03T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Windows tabanlı olan <strong>Servis</strong> <strong>Yönelimli Mimari(Service Oriented Architecture) </strong>tekniklerinden biriside .Net Remoting' dir. .Net Remoting mimarisi ağırlıklı olarak <strong>TCP</strong> bazlı ve <strong>Binary</strong> tabanlı paket iletiminde kullanılır. En büyük özelliklerinden birisi, sadece Windows işletim sistemlerinden oluşan ağlarda koşabilmesidir. Elbette <strong>HTTP</strong> üzerinden <strong>SOAP-Simple Object Access Protocol</strong> formatına uygun alt yapı kurulmasıda mümkündür. Bu sayede internet ağındada ektin şekilde kullanılabilir. Ancak Windows bağımlı olması platform bağımsızlığını ortadan kaldırmaktadır. Günümüzde <strong>WCF(Windows Communication Foundation)</strong> gibi daha ölçeklenebilir(Scalable), birleştirilmiş(Unified) bir Servis Yönelimli Mimari(SOA) açılımıda mevcuttur. Bu durumda geliştiricilerin karşısına önemli bazı sorular ve sorunlar çıkmaktadır. İşte bunlardan bir kaçı;</p>
<ul>
<li>Var olan .Net Remoting alt yapısı, WCF tabanlı bir hale dönüştürülebilir mi?</li>
<li>Dönüştürülürse ne gibi düzenlemeler yapmak gerekir?</li>
<li>Sıfırdan WCF tabanlı bir model geliştirmek yerine, .Net Remoting WCF'e göç etmek mantıklı mıdır?</li>
<li>.Net Framework 2.0 hatta 1.1 uyumlu sistemler üzerine kurulmuş senaryolarda, var olan .Net Remoting uygulamalarında yapılacak WCF düzenlemeleri geçerli olacak mıdır? Yoksa bu makinelere Framework 3.0 yüklenmeli midir?</li>
</ul>
<p>Bu sorular farklı açılardan bakıldığında artabilir. İlerleyen kısımlarda bu sorulara ve beraberinde gelen sorunlara cevap bulmamızı kolaylaştıracak şekilde ilerlemeye çalışacağız.</p>
<blockquote>
<p>Windows Communication Foundation, <strong>.Net Remoting</strong>, <strong>Web Servisleri</strong>, <strong>MSMQ</strong>,<strong> Named Pipes</strong>, <strong>WSE</strong> gibi pek çok dağıtık mimari modelini tek bir çatı altında birleştirip sunabilmesiyle ön plana çıkmış bir <strong>Servis Yönelimli Mimari(Service Oriented Architecture)</strong> alt yapısıdır. Bu alt yapı, önceki mimarilerde daha fazla kodlama gerektiren yada geliştiricileri zorlayan standartların(Örneğin <strong>WS-Specifications</strong>) kolay ve etkin bir şekilde uygulanabilmesini hatta bir arada tutulabilmesine de izin vermektedir.</p>
</blockquote>
<p>Bazı durumlarda çalışmakta olan sistemi yeni bir mimariye adapte etmenin maliyeti çok yüksek olabilir. Söz gelimi ölçek olarak çok büyük çaplı projelerde sistemi yeniden tasarlamak son derece sancılı bir süreç olabilir. Ancak böyle bir durum söz konusu değilse karşımızda iki alternatif olacaktır. Var olan sistemi modifiye ederek WCF' e taşımak yada sıfırdan tasarlamak. Aslında var olan bir .Net Remoting alt yapısını bir kaç küçük değişiklik ile WCF' e taşımak son derece kolaydır. Herşeyden önce .Net Remoting içerisinde yer alan temel parçaları göz önüne alarak ilerlemekte yarar vardır.</p>
<p>.Net Remoting ile hazırlanmış bir sistemde<strong> istemcilerin(Clients)</strong> kullanacakları fonksiyonellikleri barındıran <strong>uzak nesneler(Remote Objects)</strong> bir <strong>sunucu(Server) </strong>uygulama üzerinden <strong>Client Activated Object </strong>yada <strong>Server Activated Object</strong> modeline uygun olacak şekilde yayınlanırlar. Hatta SAO nesneleride <strong>Singleton</strong> veya <strong>SingleCall</strong> olarak tasarlanırlar. İstemci uygulamalar aslında uzak nesne referanslarını kullanırken bu referanslar <strong>Marshal By Reference</strong> modeline göre sunucu üzerinde örneklenirler. Bir başka deyişle istemci uzak nesneyi sanki kendi <strong>uygulama alanı(Application Domain) </strong>içerisindeymiş gibi kullanırlarken, tüm işlevler sunucu üzerinde gerçekleşmektedir.</p>
<p>Çok doğal olarak burada istemci ve sunucu arasındaki mesaj trafiğinin ortak bir zemine oturtulması şarttır. Bu nedenle genellikle istemci ve sunucu uygulamalar hizmete ait nesne tasarımını içeren şartnamelerin yer aldığı bir <strong>arayüz(Interface)</strong> tipini ortaklaşa referans ederler. Böylece servis tarafındaki fonkisyonelliklerin iç yapılarının değiştirilmesi halinde istemciler üzerinde yeniden güncelleme yapılmasına gerek kalmayacaktır. Ayrıca istemciler sadece arayüzü görebildiklerinden, çağırdıkları fonksiyonelliklerin iç yapısını bilmeyeceklerdir ki buda servis kodunun tam olarak istemci tarafından görülmesini engellemektedir. Zaten WCF' in tamamen arayüzlere dayalı bir sistemi önermesinin ve kullanmasının en önemli nedenleride bunlardır.</p>
<p>Bu noktada geliştirici tarafından tanımlanan <strong>serileştirilebilir tiplerinde (Serializable Types) </strong> ortak bir <strong>sınıf kütüphanesi(Class Library)</strong> üzerinde olması gerekmektedir. Serileştirilebilir nesneler aslında servis tarafında örneklenip sadece <strong> varlıkları(Entities) </strong>istemci tarafına aktarılan örnekler olarak düşünülebilir. Söz gelimi istemcinin talep ettiği bir ürünün, Product isimli bir sınıfa ait nesne örneği olacak şekilde servis tarafında doldurulması ve istemciden elde edilmesi buna örnek olarak verilebilir. Burada istemcinin talebi sonrasında servis tarafından dönen veriler Product isimli sınıfın <strong>özellik(Property) </strong>veya <strong> alanlarının(Fields) </strong>değerleridir. Serileştirilebilir nesnelerin WCF mimarisinde ele alınması çok daha kolaydır. Özellikle <strong>versiyonlamanın(Versioning)</strong> WCF üzerinden gerçekleştirilmesi daha esnektir.</p>
<blockquote>
<p>Makalenin konusu .Net Remoting' den WCF' e bir iki adımda taşınmanın nasıl sağlanabileceğini göstermek olduğundan, .Net Remoting ve WCF mimarilerinin çok geniş detayları göz ardı edilmektedir.</p>
</blockquote>
<p>Artık bir örnek üzerinden hareket ederek devam edebiliriz. Öncelikli olarak bir <strong>.Net Remoting</strong> uygulamasını <strong>Visual Studio 2005</strong> üzerinden geliştiriyor olacağız. İlk olarak istemci ve servis uygulamasının ortaklaşa kullanacağı <strong> sınıf kütüphanesini(Class Library)</strong> tasarlayarak işe başlanabilir. Sınıf kütüphanesi içerisindeki tiplere ait <strong>sınıf diyagramı(Class Diagram) </strong>ve kod içerikleri aşağıdaki gibidir.</p>
<p><img src="/makale/images/mk233_1.gif" alt="" width="289" height="308" border="0" /></p>
<p><strong>IProductManager arayüzü(Interface);</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
namespace AdvLibrary
{
public interface IProductManager
{
Product GetProductInfo(int productId);
}
}</pre>
<p>Örneğin daha basit olarak ele alınabilmesi için arayüz(Interface) tanımlamasında, geriye Product tipinden nesne örneği döndürebilen ve integer tipinden bir parametre alabilen GetProductInfo isimli bir metod bildirimi yer almaktadır.</p>
<p><strong>Product sınıfı(Class);</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
namespace AdvLibrary
{
[Serializable]
public class Product
{
public int Id;
public string Name;
public double ListPrice;
}
}</pre>
<p>Product isimli sınıf içerisinde bir ürüne ait Id, Name ve ListPrice değerleri tutulmaktadır. Bununla birlikte Product sınıfı için dikkat çekici en önemli özelliklerden biriside<strong> Serializable niteliği(attribute)</strong> ile imzalanmış olmasıdır. Burada açık bir şekilde Product sınıfına ait nesne örneklerinin <strong>Marshal By Value</strong> olarak sunucudan istemciye serileşerek taşınabileceği garanti altına alınmaktadır.</p>
<p>Servis tarafında yer alan program, söz konusu örnekte bir <strong>Console</strong> uygulaması olarak tasarlanmaktadır. Bu uygulamanın çok doğal olarak yukarıda tasarlanan tipleri içeren AdvLibrary isimli <strong>sınıf kütüphanesini(Class Library)</strong> referans ediyor olması gerekmektedir. Nitekim sunucu uygulama içerisinde asıl iş yapan sınıfın uyarlayacağı arayüz ve kullanacağı serileştirilebilir tip bu sınıf kütüphanesi içerisinde bulunmaktadır.</p>
<blockquote>
<p>Gerçek hayat senaryolarında en çok tercih edilen .Net Remoting yöntemi, sunucu uygulamasını bir <strong>Windows Service</strong> olarak tasarlamaktadır. Bu yönetimi daha güçlü olan, ölçeklenebilir ve güvenli bir uygulama seçimidir. Bunun dışında <strong>IIS(Internet Information Services)</strong> üzerinden <strong>barındırma(Host)</strong> imkanıda bulunmaktadır. Diğer taraftan sunucu uygulama bir Windows uygulaması hatta bu örnekte olduğu gibi bir Console uygulamasıda olabilir.</p>
</blockquote>
<p>Tekrar sunucu uygulamasına dönülecek olursa, IProductManager isimli <strong>arayüzü(Interface) </strong>uygulayan uzak nesne sınıfının aşağıdaki gibi tasarlanabileceği düşünülebilir.</p>
<p><img src="/makale/images/mk233_2.gif" alt="" width="294" height="188" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using AdvLibrary;
using System.Data.SqlClient;
namespace ServerApp
{
public class ProductManager:MarshalByRefObject,IProductManager
{
public ProductManager()
{
Console.WriteLine("ProductManager nesnesi oluşturuldu...");
}
#region IProductManager Members
public Product GetProductInfo(int productId)
{
Product prd = null;
using (SqlConnection conn = new SqlConnection("data source=.;database=AdventureWorks;integrated security=SSPI"))
{
using (SqlCommand cmd = new SqlCommand("Select ProductId,Name,ListPrice,SellStartDate From Production.Product Where ProductId=@PrdId", conn))
{
cmd.Parameters.AddWithValue("@PrdId",productId);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
prd = new Product();
prd.Id = productId;
prd.Name = reader["Name"].ToString();
prd.ListPrice = Convert.ToDouble(reader["ListPrice"]);
}
reader.Close();
}
}
return prd;
}
#endregion
}
}</pre>
<p>Bu sınıf içerisinde yer alan metod uyarlamasında AdventureWorks isimli veritabanına gidilmekte ve Production <strong>şemasında(Schema) </strong>yer alan Product tablosundan parametre olarak gelen ProductID değerine sahip olan ürün bilgisi geriye döndürülmektedir. Nesne oluşumlarının kolay takip edilebilmesi amacıyla ProductManager sınıfı içerisine birde <strong>varsayılan yapıcı metod(Default Constructor)</strong> ilave edilmiştir. Burada dikkat edilmesi gereken nokta sınıfın IProductManager isimli arayüz dışında <strong>MarshalByRefObject</strong> sınıfından türemiş olmasıdır.</p>
<p>Sunucu tarafındaki Remoting ayarlarını konfigurasyon bazlı olarak aşağıdaki config dosyasında tanımlayabiliriz.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="Tcp Server" port="4500"/>
</channels>
<service>
<wellknown mode="Singleton" type="ServerApp.ProductManager,ServerApp" objectUri="ProductMng.rem" />
</service>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Konfigurasyon dosyası içerisinde tahmin edileceği üzere <strong>Wellknown</strong> bir nesne tanımı yapılmıştır. Bu nesne <strong>Singleton</strong> modeline göre çalışacaktır. Bir başka deyişle tüm istemcilerin talepleri aynı uzak nesne referansı üzerinden karşılanmaktadır. Sunucu uygulama, <strong>uzak nesne(Remote Object) </strong>için <strong>TCP</strong> bazlı 4500 numaralı portu kullanıma sunmaktadır. Buradaki konfigurasyon ayarlarının sunucu uygulama üzerinde tesis edilmesi içinde aşağıdaki başlangıç kodlarının yazılması yeterlidir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using AdvLibrary;
using System.Runtime.Remoting;
namespace ServerApp
{
class Program
{
static void Main(string[] args)
{
RemotingConfiguration.Configure("..\\..\\App.config",false);
Console.WriteLine("Sunucu dinlemede. Kapatmak için bir tuşa basınız...");
Console.ReadLine();
}
}
}</pre>
<p>Bu noktada şunu hatırlamakta yarar vardır; sunucu uygulama çalıştığı sürece istemcilerden gelecek taleplere cevap verilebilir.</p>
<p>Gelelim istemci uygulamaya. Herşeyden önce istemci uygulamanında arayüzü barındıran ortak kütüphaneyi referans etmesi gerekmektedir. Diğer taraftan istemci uygulamanın kod içeriği aşağıdaki gibi olabilir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using AdvLibrary;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
IProductManager prdMng = (IProductManager)Activator.GetObject( typeof(IProductManager), "tcp://localhost:4500/ProductMng.rem");
Product prd=prdMng.GetProductInfo(1);
Console.WriteLine(prd.Name+" "+prd.ListPrice.ToString("C2"));
Console.ReadLine();
}
}
}</pre>
<p>Burada en kritik nokta, <strong> arayüz(interface)</strong> tercihi nedeniyle <strong>Activator</strong> sınıfının <strong> GetObject</strong> metodunun kullanılmasıdır. Bu metod ile aslında ikinci parametre ile belirtilen adresten ProductMng.rem isimli tanımlayıcının<strong>(Uniform Resource Identifier)</strong> işaret ettiği uzak nesne referansı talep edilmektedir. İstemciye döndürülecek olan referansın taşınabileceği tek yer IProductManager arayüzü olduğundan da metodun dönüş tipi <strong> bilinçli(Explicit)</strong> olarak çevrilmektedir. Buraya kadar yapılan hazırlıklar sonucunda test işlemi yapılırsa aşağıdakine benzer çıktılar elde edilir.</p>
<p><img src="/makale/images/mk233_3.gif" alt="" width="363" height="335" border="0" /></p>
<p>Görüldüğü gibi istemciler başarılı bir şekilde sunucu üzerinden taleplerini karşılayabilmektedirler. <em>(Burada oluşturulan sistemin düzgün çalıştığının kontrol edilmesi için sunucu uygulama çalıştırılmadan bir istemcinin çalıştırılması denenebilir. Eğer gerçekten sunucu üzerindeki nesne kullanılmaya çalışılıyorsa çalışma zamanında istemci tarafında <strong>"No Connection Could Be Made, Becouse the Target Machine Actively Refused It..." </strong>hatası alınır.) </em></p>
<p>Buraya kadar anlatılanlar basit olarak bir <strong>.Net Remoting </strong>uygulamasının alt yapısını özetlemektedir. Aşağıdaki şekil üzerinden, yapılanlar ve sonuçları tartışılabilir.</p>
<p><img src="/makale/images/mk233_4.gif" alt="" width="546" height="404" border="0" /></p>
<p>Şekilde .Net Remoting içerisinde 50000 metre yukarıdan bakıldığında göze çarpan etkenler betimlenmeye çalışılmıştır. Şimdi bu sistemi <strong>Windows Communication Foundation</strong> alt yapısına taşımaya çalışıyor olacağız.</p>
<p>İlk yapılması gereken servis tarafında sunulmak istenen fonksiyonellikleri tanımlayacak bir sözleşme(Contract) oluşturmaktır. Burada söz konusu olan <strong>servis sözleşmesi(Service Contract) </strong>bir arayüze rahatlıkla uygulanabilir. Tek yapılması gereken <strong>System.ServiceModel.dll</strong> isimli <strong>.Net Framework 3.0 assembly</strong>' ının referans edilmesi ve <strong>ServiceContract</strong> ile <strong> OperationContract niteliklerinin(attributes)</strong> kullanılmasıdır. Aşağıdaki şekilde Visual Studio 2005 üzerinden söz konusu assembly' ın referans edilişi görülmektedir.</p>
<p><img src="/makale/images/mk233_5.gif" alt="" width="268" height="451" border="0" /></p>
<p>Bu işlemin ardından IProductManager isimli arayüzün yapısı aşağıdaki gibi değiştirilmelidir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.ServiceModel;
namespace AdvLibrary
{
[ServiceContract]
public interface IProductManager
{
[OperationContract]
Product GetProductInfo(int productId);
}
}</pre>
<p>Bu değişiklik arayüzün <strong>Windows Communication Foundation</strong> uyumlu bir <strong>serviş sözleşmesi(Service Contract)</strong> olması için yeterlidir. <strong>ServiceContract</strong> niteliği ile tanımlanan servis sözleşmesi içerisinden dışarıya sunulabilecek fonksiyonelliklerin tamamı <strong>OperationContract</strong> niteliği(attribute) ile imzalanmalıdır. Yapılan bu değişiklik her ne kadar ortak kütüphane içerisinde olsada sonuç itibariyle tüm istemcilere gerekli assembly' ın yeniden dağıtılması gerekmektedir. Ama zaten bu göz önüne alınması gereken bir aşamadır.</p>
<p>Gelelim sunucu tarafına. Sunucu tarafındada çok doğal olarak yapılması gereken bazı işlemler vardır. Herşeyden önce konfigurasyon içeriğinin WCF mimarisine uyumlu olacak şekilde değiştirilmesi gerekmektedir. Bu amaçla sunucu uygulama tarafındaki <strong> App.config</strong> dosyasının içeriği aşağıdaki gibi yenilenmelidir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!--<system.runtime.remoting>
<application>
<channels>
<channel ref="Tcp Server" port="4500"/>
</channels>
<service>
<wellknown mode="Singleton" type="ServerApp.ProductManager,ServerApp" objectUri="ProductMng.rem" />
</service>
</application>
</system.runtime.remoting>-->
<system.serviceModel>
<services>
<service name="ServerApp.ProductManager">
<endpoint address="net.tcp://localhost:4500/ProductMng" binding="netTcpBinding" contract="AdvLibrary.IProductManager" />
</service>
</services>
</system.serviceModel>
</configuration></pre>
<p><strong>Windows Communication Foundation(WCF)</strong> mimarisinde servis için belkide en önemli kavram <strong> EndPoint</strong>' dir. EndPoint içerisinde <strong>WCF mimarisinin ABC' si </strong> yer almaktadır. <strong>AddressBindingConfiguration</strong> yardımıyla servisin hangi lokasyondan, hangi protokol ile, hangi nesneyi nasıl ve ne şekilde sunduğu belirtilmektedir.<strong> .Net Remoting</strong> bazlı geliştirilen örnekte <strong>TCP</strong> bazlı ve <strong>Binary </strong>serileştirme yapan bir sistem kullanıldığından bu özellikleri bünyesinde barındıran bir tipin WCF tarafında ele alınması gerekmektedir. Bu işi <strong>NetTcpBinding</strong> isimli sınıf üstlenmektedir. Bu aynı zamanda <strong>bağlayıcı tiptir(Binding Type)</strong>. <strong>Contract</strong> bilgisi ile tahmin edileceği üzere servisin dış ortama sunduğu sözleşme ve operasyonları belirtilmektedir. Son olarak <strong> Address</strong> bilgisi ile servis üzerinde sunulan nesneye hangi adres üzerinden erişilebileceği belirtilmektedir.</p>
<blockquote>
<p><strong>WCF</strong> mimarisinde bir servis birden fazla <strong>EndPoint</strong> sunabilir. Bu geliştiricilere senaryoya göre birden fazla bağlayıcı tipin(Binding Type) ve dolayısıyla imkanın sunulabildiği bir ortam hazrılayacaktır. Söz gelimi bir servis uygulaması WCF' e göre yazıldığında, <strong>MSMQ</strong>, <strong>TCP</strong>, <strong>HTTPS</strong> üzerinden vb... hizmet verebilecek mesaj seviyesinde(Message Level) yada iletişim seviyesinde(Transport Level) korumalı hizmetleri sunabilir. Üstelik bunlar için ayrı ayrı uygulama çeşitleri tasarlanmasına gerek kalmaz. Bir başka deyişle bu tip bir senaryo için ayrı bir .<strong>Net Remoting, Xml</strong> <strong>Web</strong> <strong>Service</strong> veya <strong>MSMQ</strong> uygulaması yazılmasına gerek yoktur. İşte WCF' in birleştirici rolünün önemi burada belirgin bir biçimde ortaya çıkmaktadır.</p>
</blockquote>
<p>Elbetteki sunucu uygulamanın kodlarınıda aşağıdaki gibi değiştirmek gerekmektedir. Artık <strong> ServiceHost</strong> isimli sınıf başlatıcı rolü üstlenmektedir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using AdvLibrary;
//using System.Runtime.Remoting;
using System.ServiceModel;
namespace ServerApp
{
class Program
{
static void Main(string[] args)
{
//RemotingConfiguration.Configure("..\\..\\App.config",false);
ServiceHost host = new ServiceHost(typeof(ProductManager));
host.Open();
Console.WriteLine("Sunucu dinlemede. Kapatmak için bir tuşa basınız...");
Console.ReadLine();
host.Close();
}
}
}</pre>
<p>Örnek koda göre <strong>ServiceHost</strong> nesne örneği, ProductManager isimli sınıfı uzak nesne olarak hizmete açmaktadır. <strong>Open</strong> metoduna yapılan çağrıdan sonra, sunucu uygulama istemciden gelecek olan talepleri dinleyecek konuma gelmektedir. <strong> Close</strong> metoduna yapılan çağrı sonrasında ise servis kapatılmaktadır. Elbette <strong>ServiceHost</strong> sınıfının kullanılabilmesi için <strong> System.ServiceModel.dll</strong> <strong>assembly</strong>' ının sunucu uygulama tarafınada referans edilmesi gerekmektedir.</p>
<p>Peki istemci tarafında neler yapılmalıdır? Herşeyden önce istemci tarafında gerekli ayarların konfigurasyon bazlı olacak şekilde geliştirilmesi önerilmektedir. Bu amaçla istemci tarafına eklenecek olan bir konfigurasyon dosyasının içeriği, örneğe göre aşağıdaki gibi tasarlanabilir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="ProductMng" address="net.tcp://localhost:4500/ProductMng" binding="netTcpBinding" contract="AdvLibrary.IProductManager"/>
</client>
</system.serviceModel>
</configuration></pre>
<p>Konfigurasyon içeriğine bakıldığında dikkat edileceği üzere yine bir <strong>EndPoint</strong> tanımlaması yapılmaktadır. Bu EndPoint aslında istemcinin bağlantı kuracağı servis tarafındaki noktayı tanımlamaktadır. İstemci tarafındaki kod içeriği ise aşağıdaki gibi geliştirilebilir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using AdvLibrary;
using System.ServiceModel;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
//IProductManager prdMng = (IProductManager)Activator.GetObject(typeof(IProductManager), "tcp://localhost:4500/ProductMng.rem");
//Product prd=prdMng.GetProductInfo(1);
ChannelFactory<IProductManager> chn = new ChannelFactory<IProductManager>("ProductMng");
IProductManager prdMng=chn.CreateChannel();
Product prd = prdMng.GetProductInfo(1);
Console.WriteLine(prd.Name+" "+prd.ListPrice.ToString("C2"));
Console.ReadLine();
}
}
}</pre>
<p><strong>ChannelFactory</strong> nesne üretimi için gerekli bilgileri, parametre olarak verilen değere göre konfigurasyon dosyasından almaktadır. Böylece servis tarafındaki hangi <strong>EndPoint</strong> ile konuşabileceğini bilmektedir. <strong>CreateChannel</strong> metodu önceden hazırlanan ayarlara göre, servis tarafı ile konuşacak olan kanal nesnesini örneklemektedir. Açıkçası CreateChannel metodunun sonucu <strong> .Net Remoting </strong>için kullanılan <strong>Activator.GetObject</strong> metodunun ürettiğine benzerdir. Nitekim aşağıdaki ekran görüntüsünden de anlaşılacağı üzere <strong>CreateChannel</strong> metoduda <strong>Transparent</strong> bir <strong>Proxy</strong> üretmektedir. Bu Proxy, çalışma zamanında servis üzerindeki <strong> EndPoint</strong> ile haberleşmektedir.</p>
<p><img src="/makale/images/mk233_7.gif" alt="" width="639" height="166" border="0" /></p>
<p>Çok doğal olarak <strong>proxy</strong> nesnesinin üretilmesinde de kullanılan <strong>ChannelFactory</strong> sınıfı <strong> System.ServiceModel isim alanı(Namespace) </strong>altındadır. Bu nedenle söz konusu isim alanını içeren <strong>assembly</strong>' ın istemci uygulamayada referans edilmesi gerekmektedir.</p>
<p>Artık var olan .Net Remoting uygulaması bu bir kaç adım ile <strong>WCF</strong> formatına çevrilmiştir. Uygulamalar test edildiğinde aşağıdakine benzer sonuçlar alınacaktır.</p>
<p><img src="/makale/images/mk233_6.gif" alt="" width="464" height="308" border="0" /></p>
<p>Elbetteki servisin ve operasyonların davranışları <strong>WCF</strong> mimarisi içerisinde çok daha geniş bir şekilde ele alınmaktadır. Örnekte bunlara gerek kalmadanda WCF' e geçilebileceği gösterilmektedir. Ancak ele alınması gereken başka noktalarda olabilir.</p>
<p>Örneğin her istemci için birer uzak nesne referansı sunucu üzerinde oluşturulmaktadır. Oysaki tasarlanan <strong> .Net Remoting </strong>alt yapısında <strong>Singleton</strong> modeli benimsenmiştir. Bir başka deyişle her istemci talebi(Request) aynı uzak nesne örneği üzerinden karşılanmaktadır. <strong>WCF</strong> tarafında bu, servis tarafında sunulan uzak nesnenin bir <strong>çalışma zamanı(run-time)</strong> davranışıdır(Behavior). Dolayısıyla bu davranışın bir <strong>nitelik(attribute)</strong> yardımıyla belirlenmesi yada konfigurasyon içeriğinde tanımlanması gerekmektedir. Bu sebepten örnekte yer alan ProductManager sınıfı başında <strong>ServiceBehavior</strong> niteliğinin(attribute) aşağıdaki gibi kullanılması gerekir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class ProductManager:MarshalByRefObject,IProductManager</pre>
<p><strong>InstanceContextMode</strong> <strong>enum</strong> sabitinin <strong>Single</strong> olarak belirlenen değeri örnekte ele alınan senrayoya uygun olacak şekilde uzak nesne referanslarının oluşturulmasını sağlamaktadır. Bunun sonucunda çalışma zamanındaki durum aşağıdaki gibi olacaktır.</p>
<p><img src="/makale/images/mk233_10.gif" alt="" width="453" height="271" border="0" /></p>
<p>Bunun dışında binary olarak serileştirilebilen Product sınıfı için herhangibir ekstra çalışma yapılmadığı ortadadır. Nitekim böyle bir çalışma yapılmasına gerek kalmamıştır. Fakat <strong>versiyonlama</strong> yapıldığı durumlarda WCF mimarisi<strong> .Net Remoting</strong>' e göre daha efektif bir çözüm sunmaktadır.</p>
<p>Burada <strong>versiyonlamanın(Versioning)</strong> nasıl sorunlar yaşatabileceğini anlamak önemlidir. Söz gelimi Product isimli serileştirilebilir sınıfın sonradan yazılan ikinci bir versiyonu olduğu ve bu versiyonda işin içerisine <strong>SellStartDate</strong> isimli yeni bir alan(Field) katıldığı göz önüne alınsın. Eski Product sınıfını kullanan istemcilerin sorunsuz olarak onunla çalışmaya devam etmelerini, yeni versiyonu kullananların ise yeni eklenen alanı ele alabilmelerini sağlamak için kuvvetle muhtemel tasarımı aşağıdaki gibi değiştirmek gerekecektir.</p>
<p><img src="/makale/images/mk233_8.gif" alt="" width="451" height="285" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Runtime.Serialization;
namespace AdvLibrary
{
[Serializable]
public class Product:ISerializable
{
public int Id;
public string Name;
public double ListPrice;
public DateTime SellStartDate; // Yeni versiyonlar için eklenen alan.
public Product()
{
}
public Product(SerializationInfo info, StreamingContext context)
{
Id = info.GetInt32("Id");
Name = info.GetString("Name");
ListPrice = info.GetDouble("ListPrice");
// Versiyonlama nedeni ile oluşabilecek hataları görmezden gelmek için bir try...catch
try
{
SellStartDate = info.GetDateTime("SellStartDate");
}
catch
{
}
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Id", Id);
info.AddValue("Name", Name);
info.AddValue("ListPrice", ListPrice);
info.AddValue("SellStartDate", SellStartDate); // Yeni versiyon için ekenen kod satırı
}
#endregion
}
}</pre>
<p>Burada dikkat edilecek olursa serileştirme işlemleri <strong>ISerializable</strong> <strong>arayüzünün(Interface)</strong> kullanılmasıyla özelleştirilerek, değerlerin aktarımı kontrollü bir hale getirilmektedir. Özelleştirme için <strong>ISerializable</strong> arayüzünün uygulanması haricinde yapıcı metodun(Constructor) aşırı yüklenmiş(Overload) bir versiyonuda ele alınmaktadır. Sorunun detayları çok önemli olmamakla birlikte Windows Communication Foundation içerisinde bu tip versiyonlamalarında kontrol edilebilmesi son derece kolaydır. Tek yapılması gereken aşağıdaki gibi Product sınıfını bir <strong>veri sözleşmesi(Data Contract)</strong> haline getirmektir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Runtime.Serialization;
namespace AdvLibrary
{
[DataContract]
public class Product
{
[DataMember(IsRequired=true)] // Mutlaka olmalı
public int Id;
[DataMember(IsRequired = true)] // Mutlaka olmalı
public string Name;
[DataMember(IsRequired = true)] // Mutlaka olmalı
public double ListPrice;
[DataMember] // Opsiyonel oldu.
public DateTime SellStartDate; // Yeni versiyonlar için eklenen alan.
}
}</pre>
<p><strong>DataMember</strong> <strong> niteliği(attribute)</strong> varsayılan olarak uygulandığı üyeye opsiyonel bir davranış getirmektedir. Bir başka deyişle çalışma zamanında karışa tarafın bu alanı içermeyen bir tipi kullanması halinde hiç bir problem oluşmayacak ve bu alan görmezden gelinecektir. Tam tersine bu alanı kullanan bir versiyon varsa SellStartDate alanıda hesaba katılacaktır. Bu sayede versiyonlamada çok kolay bir şekilde ele alınabilmektedir. Product sınıfının tasarlanmasında dikkat edilmesi gereken önemli bir nokta vardır. Buna göre <strong>DataContract</strong> ve <strong> DataMember</strong> <strong>niteliklerinin(attributes)</strong> tanımlandıkları isim alanı(Namespace), <strong>System.Runtime.Serialization.dll </strong>assembly' ı içerisindedir. Dolayısıyla sınıf kütüphanesine bu assembly' ın aşağıdaki ekran görüntüsünde olduğu gibi referans edilmesi gerekmektedir.</p>
<p><img src="/makale/images/mk233_9.gif" alt="" width="487" height="342" border="0" /></p>
<p>Son olarak ele alınması gereken bir durum daha olabilir. İstemci ve servis tarafının <strong>.Net Framework 2.0</strong> yüklü sistemler olduğu göz önüne alındığında yapılan son değişikliker sonrasında uygulamalar sorunsuz bir şekilde çalışabilecek midir?<em>( Burada iyimser bir yaklaşım güdülerek .Net Framework 1.1 versiyonu hiç hesaba katılmamıştır.)</em></p>
<blockquote>
<p>Yukarıdaki referans ekleme kısmında dikkat çeken noktalardan biriside <strong>Framework 3.0</strong> için geliştirilmiş pek çok <strong>assembly</strong>' ın <strong>çalışma zamanında(Run Time) v2.0.50727 </strong>versiyonuna ihtiyaç duymasıdır. Bir başka deyişle <strong>System.ServiceModel </strong>veya <strong> System.Runtime.Serialization</strong> gibi 3.0 assembly' ları,<strong> .Net Framework 2.0</strong> yüklü bir makinede belleğe yüklenip çalışabilirler. Nitekim ihtiyaçları olan <strong>v2.0.50727 </strong> versiyonlu <strong>Common Language Runtime(CLR)</strong>' dır.</p>
</blockquote>
<p>Aslında sistemler üzerinde .Net Framework 3.0' ın yüklü olması sorunun çözümü için yeterlidir. Lakin sadece .Net Framework 2.0 yüklü olan bir sistemde değiştirilen uygulamalar çalıştırılabilirse, bir .Net Framework 3.0 yükleme derdinden kurtulunabilinir. Ancak bunun bir dert olup olmadığıda tartışılması gereken bir vakadır.</p>
<p>Söz konusu durumu <span style="text-decoration: underline;">test etmek için servis veya istemci uygulamaları, üzerinde <strong>.Net Framework 2.0</strong> yüklü olan bir sistemde, <strong>System.ServiceModel.dll </strong>ve <strong>System.Runtime.Serialization.dll assembly</strong>' larınıda kopyalayarak çalıştırmak yeterli olacaktır. Başlangıçta servis ve istemci tarafında var olması düşünülen exe, config ve dll dosyaları aşağıdaki gibidir.</span></p>
<p><img src="/makale/images/mk233_11.gif" alt="" width="479" height="393" border="0" /></p>
<p>Ne yazıkki buradaki dll' lerin hedef bilgisayara(bilgisayarlara) taşınmaları yeterli olmamaktadır. <strong>.Net Framework 2.0</strong> yüklü makinede örnek olarak ServerApp uygulaması çalıştırıldığında aşağıdaki ekran görüntüsünde yer alan hata ile karşılaşılabilir.</p>
<p><strong><span style="font-family: Verdana; color: #ff0000;"> <img src="/makale/images/mk233_12.gif" alt="" width="639" height="301" border="0" /></span></strong></p>
<p>Bunun üzerine <strong>SMDiagnostics.dll</strong> isimli assembly' ında hedef bilgisayarda <strong>ServerApp</strong> ve <strong> ClientApp</strong> program dosyalarının olduğu yere konması gerekir. Söz konusu assembly hedef programların bulunduğu lokasyona taşındıktan sonra bir deneme daha yapılırsa aşağıdakine benzer bir hata mesajı ile daha karşılaşılabilinir.</p>
<p><strong><span style="font-family: Verdana; color: #ff0000;"> <img src="/makale/images/mk233_16.gif" alt="" width="641" height="231" border="0" /></span></strong></p>
<p>Bu hatanın oluşmasının en büyük nedeni, programın çalıştığı makine üzerinde <strong>.Net Framework 3.0</strong> yüklü olmadığı için, <strong>machine.config</strong>' de olması gereken bazı ayarların bulunmayışından kaynaklanmaktadır. Bu nedenle <strong>ServiceModelReg</strong> aracının kullanılarak gerekli konfigurasyon bilgilerinin hedef makineye yüklenmesi gerekecektir. Bu sebepten komut satırından aşağıdaki gibi bir çalışma yapılmalıdır.</p>
<p><strong><span style="font-family: Verdana; color: #ff0000;"> <img src="/makale/images/mk233_14.gif" alt="" width="596" height="249" border="0" /></span></strong></p>
<p>Bu çalışmanın ardından hedef bilgisayarda yer alan konfigurasyon dosyas için gerekli Handler ve Module yüklemeleri gerçekleştirilecektir. Artık herşey halloldu diye düşünülebilir ama bu seferde ServerApp uygulaması çalıştırıldığında aşağıdakine benzer bir hata mesajı daha alınabilir.</p>
<p><strong><span style="font-family: Verdana; color: #ff0000;"> <img src="/makale/images/mk233_15.gif" alt="" width="638" height="231" border="0" /></span></strong></p>
<p>Çok doğal olarak <strong> System.IdentityModel.dll</strong>' ininde kopyalanmış olması gerekecektir. Bu hata beraberinde <strong>System.IdentityModel.Selectors.dll</strong> isimli assembly' ında yüklenmesini gerektirmektedir. Her iki <strong>assembly</strong> yüklensede bu kez <strong>doğrulama(Authentication)</strong> ve <strong> yetkilendirme(Authorization)</strong> problemleri oluşmaktadır. Bunların çözümü adına config dosyalarında gerekli düzenlemele yapılabilir. Yinede bu sancılı süreç hemen çözümlenemeyecektir. Yazının ilerleyen kısımlarında konunun daha fazla dağılmaması adına bu yöntemler göz ardı edilmiştir.</p>
<p>Sonuç olarak her ne kadar <strong>.Net Remoting</strong>' den <strong>Windows Communication Foundation </strong>tarafına geçiş yapmak kolay olsada, gerçek çalışma ortamında özellikle<strong> .Net Framework 2.0</strong> yüklü sistemlerde bazı ayarlamaların yapılması gerekmektedir. Bu durum .Net Framework 1.1 yüklü makinelerde tam bir kabus haline gelebilir. Nitekim kopyalanan dll' lerin bazıları <strong>CLR 1.1</strong> versiyonunda çalışmayacaktır. Bu nedenle <strong>.Net Framework 3.0</strong>' ın <strong>Redistruable</strong> paketinin hedef sistemlere yüklenerek çalışmalara devam edilmesi doğru bir davranış olacaktır. Hatta istemciler için bir setup paketinin hazırlanması ve gerekliliklerden birisi olarak .Net Framework 3.0 seçiminin eklenmesi çok yerinde bir davranıştır. O halde cevaplanması gereken bir soru daha vardır. Bu kadar zahmete girilecekse, sistemin WCF için yeninde yazılması yoluna gidilemez midir? Aslında bu sorunun cevabı daha önceden tasarlanıp kullanılılmakta olan .Net Remoting sistemine bağlıdır. Eğer yazılan çok fazla kod ve birbirlerine bağlı parça var ise, bir iki düzenleme ile WCF' e uyumlu bir sistem oluşturmak son derece kolaydır.</p>
<p>Bu noktalarda vakayı doğru değerlendirip karar vermekte ve gerekirse cevap için profesyonel destek almakta yarar olabilir.Böylece geldik bir makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/makale/images/FromRemotingToWCF.rar">Örnek Uygulama için Tıklayın</a></p>2007-12-03T12:00:00+00:00wcfwindows communication foundation.net remotingmigrationbsenyurtWindows tabanlı olan Servis Yönelimli Mimari(Service Oriented Architecture) tekniklerinden biriside .Net Remoting' dir. .Net Remoting mimarisi ağırlıklı olarak TCP bazlı ve Binary tabanlı paket iletiminde kullanılır. En büyük özelliklerinden birisi, sadece Windows işletim sistemlerinden oluşan ağlarda koşabilmesidir. Elbette HTTP üzerinden SOAP-Simple Object Access Protocol formatına uygun alt yapı kurulmasıda mümkündür. Bu sayede internet ağındada ektin şekilde kullanılabilir. Ancak Windows bağımlı olması platform bağımsızlığını ortadan kaldırmaktadır. Günümüzde WCF(Windows Communication Foundation) gibi daha ölçeklenebilir(Scalable), birleştirilmiş(Unified) bir Servis Yönelimli Mimari(SOA) açılımıda mevcuttur. Bu durumda geliştiricilerin karşısına önemli bazı sorular ve sorunlar çıkmaktadır.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=2d06021d-7d35-4e71-b692-cb2dc74848290https://www.buraksenyurt.com/trackback.axd?id=2d06021d-7d35-4e71-b692-cb2dc7484829https://www.buraksenyurt.com/post/-Net-Remoting-Dunyasc4b1ndan-WCFe-Gecmek-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=2d06021d-7d35-4e71-b692-cb2dc7484829https://www.buraksenyurt.com/post/-Net-Remoting-SoapSuds-bsenyurt-com-dan.Net Remoting - SoapSuds2006-06-21T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Remoting mimarisinde, istemci ve sunucu arasında uzak nesneleri paylaşmanın dört farklı yolu vardır. İstemcilerin tek amacı sunucu üzerinde yer alan uzak nesne referanslarını kullanabilmektir. Bu açıdan bakıldığında, istemci uygulamanın uzak sunucu üzerindeki nesne referanslarının yapısını bilmesi gerektiği ortaya çıkmaktadır. Kullanılabilecek yollardan ilki uzak nesne sınıfının bulunduğu paylaşımlı bir assembly' ı tüm istemci uygulamalara dağıtmaktır. Bu istemci uygulamalar için ekstra kod yazmadan kolayca gerçekleştirilebilecek bir işlemdir. Lakin istemci uygulamalarda, uzak sınıfın tüm içeriğinin yer aldığı bir assembly' da mevcuttur. Bu da ILDASM (Intermediate Dis-Assembler Tool) ve başka üçüncü parti araçlar yardımıyla iş mantığının (business logic) istemci tarafından kolayca okunabileceği anlamına gelir. İşte bu dezavnataj nedeni ile özellikle güvenlik açısından çoğu zaman bu teknik tercih edilmez.</p>
<p>İkinci yöntem ve belkide en popüler olanı, uzak sınıf modelinin türetildiği bir interface tipini istemci ve sunucu arasında paylaşıma sunmaktır. Yani istemci tarafında sadece ve sadece uzak nesne modelinin bilgisini tutan bir interface tipi yer alacaktır. Bu modele göre uzak sunucu üzerindeki uzak nesne referansına polimorfizm' in bir sonucu olarak interface tipi üzerinden erişebilinir. Ama daha da önemlisi istemci tarafında, uzak nesne içerisindeki kodların kesinlikle görünmüyor oluşudur. Bu da doğal olarak iş mantığını istemciden gizleyen etkili bir tekniktir. .Net Remoting uygulamalarını yazarken çoğunlukla interface kullanımı tercih edilmektedir.</p>
<p>Üçüncü model abstract modeli ele alır ve özellikle nesne üretiminin istemciden soyutlanması söz konusu ise Fabrika Tasarım Desenini (Factory Design Pattern) uygular. Bu model içerisinde, interface modeline benzer olarak istemci tarafından iş mantığı ve özellikle uzak nesnenin üretiliş biçimi soyutlanmaktadır. Ne yazıkki bu modelin uygulanması çoğu zaman kolay değildir. Çünkü daha ileri seviye kod yazımını gerektirmektedir. Bu modelin kullanılabilmesi için abstract mimari, tasarım desenleri gibi kavramlara aşina olmak gerekir.</p>
<p>Dördüncü ve son model ise istemci tarafındaki uygulamaların, kullanmak istedikleri uzak nesneye ait metadata bilgisini sağlayan SoapSuds aracını ele alır. Bu modelde, istemci tarafında uzak nesneye ait sadece tip ve üye bilgilerini içeren bir assembly söz konusudur. Yani istemci tarafında sadece uzak nesneye ait metadata bilgisi yer alır. Bu da elbetteki iş mantığını istemciden gizleyen bir modeldir. Ancak özellikle interface ve abstract modelinin etklinliği nedeni ile SoapSuds modeli değerini kaybetmektedir. Yinede SoapSuds modelini bilmekte yarar vardır. İşte bu makalemizde SoapSuds modelini incelemeye çalışacağız. Bu modeller arasında elbetteki bir takım avantaj ve dezavantajlar söz konusudur. Örneğin interface , abstract veya soapSuds modelleri bağlantısız çalışmaya izin vermezler. Bunun en büyük nedeni elbette iş yapacak nesnel kodların istemci tarafında bulunmayışıdır. Bu tip bir ihtiyaca ancak ve ancak Paylaşımlı Assembly modeli cevap verecektir. Ancak .Net Remoting uygulamalarının tasarım amacı düşünüldüğünde bu son derece uç bir örnektir. Bahsedilen dört model arasındaki temel farklılıkları ve birbirlerine olan üstünlüklerini aşağıdaki tabloda özet olarak bulabilirsiniz.</p>
<table id="table64" style="border-collapse: collapse; width: 100%;" border="1" cellpadding="5">
<tbody>
<tr>
<td><strong>Model</strong></td>
<td><strong>Dezavantajları</strong></td>
<td><strong>Avantajları</strong></td>
</tr>
<tr>
<td>Paylaşımlı Assembly (Shared Assembly)</td>
<td>İstemci tarafından iş mantığının görülebilmesi.</td>
<td>Geliştirme kolaylığı. Bağlantılı ve bağlantısız çalışma desteği.</td>
</tr>
<tr>
<td>Interface</td>
<td>Bağlantılı ve bağlantısız katman modeline cevap verememesi.</td>
<td>İstemci tarafından iş mantığının gizlenmesi (security).</td>
</tr>
<tr>
<td>Abstract</td>
<td>Bağlantılı ve bağlantısız katman modeline cevap verememesi.<br /> <br /> Kodlamanın zor oluşu.</td>
<td>İş mantığının gizlenmesi (security) ve uzak nesne üretim işlemlerinin soyutlanması.</td>
</tr>
<tr>
<td>SoapSuds</td>
<td>Bağlantılı ve bağlantısız katman modeline cevap verememesi.<br /> <br /> Wrapped proxy seçeneğinde sadece HTTP desteği olması.</td>
<td>İş mantığının istemci tarafından gizlenmesi. (security).</td>
</tr>
</tbody>
</table>
<p><br />SoapSuds modelinde, istemci tarafında uzak nesneye ait metadata' yı içeren bir assembly üretimi söz konusudur. Framework ile gelen SoapSuds aracının en temel amacı bu assembly' ı üretmektir. Burada üretilen assembly aslında fiziki bir proxy nesnesi görevini üstlenir. Proxy' nin iki farklı üretiliş şekli vardır. Wrapped Proxy yada Non-Wrapped Proxy. Wrapped Proxy tipinde, sadece SOAP ve HTTP protokolü desteklenmektedir. Bunun dışında bu modeli uygularken istemci tarafında channel, port gibi konfigurasyon ayarlarının yapılmasına gerek kalınmaz. Çünkü bu tip bilgiler WSDL talebi sonucu üretilen Proxy Assembly' ın içerisine kaydedilmektedir. Non-Wrapped Proxy modeli ise hem HTTP hem de TCP protokolüne destek verebilmektedir(Teorik Olarak). Non-Wrapped Proxy modelinde,Wrapped Proxy Assembly' da yapılmayan konfigurasyon ayarlarının da yapılması gerekir. Hangi tip olursa olsun sonuç itibariyle SoapSuds modeli, istemcinin uzak nesneyi kullanabilmesi için gerekli bilgileri içeren bir metadata sağlar ve bunu kullanarak bir proxy assembly üretir. Şimdi dilerseniz SoapSuds modelini örnekler üzerinde incelemeye çalışalım. İlk olarak örneklerimizde kullanacağımız uzak nesneye ait sınıfımızı ve sunucu uygulamamızı tasarlayarak işe başlayacağız.</p>
<p><strong>Uzak nesne sınıfı kodları;</strong></p>
<p><img src="/makale/images/mk164_1.gif" alt="" width="307" height="235" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">namespace RemoteObjects
{
public class Matematik:MarshalByRefObject
{
public Matematik()
{
Console.WriteLine("Uzak nesne yapıcı metod çağırıldı...");
}
public double Toplam(double deger1, double deger2)
{
return deger1 + deger2;
}
}
}</pre>
<p><strong>Sunucu Uygulama;</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">class Program
{
static void Main(string[] args)
{
RemotingConfiguration.Configure("..\\..\\App.config",false);
Console.WriteLine("Sunucu dinlemede...");
Console.ReadLine();
}
}</pre>
<p><strong>Sunucu Konfigurasyon bilgisi;</strong></p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="Http Server" port="9800"/>
</channels>
<service>
<wellknown type="RemoteObjects.Matematik,RemoteObjects" objectUri="Matematik.soap" mode="Singleton"/>
</service>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Şimdi ilk olarak SopaSuds aracını sunucu üzerinde çalıştırıyor ve Wrapped Proxy' ımızı üretiyoruz. Bunun için Visual Studio.2005 Command Prompt' u kullanabiliriz. SoapSuds aracını kullanırken Proxy Assembly' ı üretebilmemiz için Sunucu uygulamanın mutlaka çalışıyor olması gerekmektedir. Bu arada yazdığımız komut satırındaki SOAP uzantısına ve WSDL (Web Service Description Language) talebine dikkat edelim. Burada oa anahtarı Output Assembly anlamına gelmektedir.</p>
<p><strong>Komut :</strong> SoapSuds -url:http://manchester:9800/Matematik.soap?wsdl -oa:MatMetaData.dll</p>
<p><img src="/makale/images/mk164_2.gif" alt="" width="639" height="315" border="0" /></p>
<p>Komutu uygularken dikkat ederseniz ?wsdl takısı kullanılıyor. Bunun sebebi Metadata' nın SOAP üzerinden elde edilen WSDL dökümanına bakılarak çıkartılmasıdır. Eğer tarayıcı penceresinden http://manchester:9800/Matematik.soap?wsdl yazarsanız aşağıdakine bezner bir ekran görüntüsü elde edersiniz. Bu web servislerinden aşina olduğumuz WSDL dökümanıdır.</p>
<p><img src="/makale/images/mk164_5.gif" alt="" width="531" height="448" border="0" /></p>
<p>Bu işlemin ardından komutu çalıştırdığımız klasörde MatMetaData.dll isimli bir assembly oluşturulduğunu görebiliriz. Bu Wrapped Proxy türündendir. Şimdi ILDASM aracı yardımıyla MatMetaData.dll ve RemoteObjects.dll' lerini birbirleriyle karşılaştıralım.</p>
<p><img src="/makale/images/mk164_3.gif" alt="" width="468" height="548" border="0" /></p>
<p>İlk olarak çıktıların aynı olmadığı hemen göze çarpmaktadır. SoapSuds ürettiği assembly içerisine WSDL' i kullanarak uzak nesneye nasıl erişeceğine dair bilgiler içeren ek üyeler atmıştır. Dahası Matematik sınıfı içerisindeki Constructor ve Toplam metodlarının MsIL kodlarına bakacak olursak, üye içi kodların yansıtılmadığını kolayca görebiliriz. Buda istemcinin, uzak nesne iş mantığına ait kodları asla göremeyeceği anlamına gelmektedir.</p>
<p><strong>MatMetaData.dll' i içindeki Matematik sınıfı için Constructor içeriği;</strong></p>
<pre class="brush:plain;auto-links:false;toolbar:false" contenteditable="false">.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 28 (0x1c)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Runtime.Remoting]System.Runtime.Remoting.Services.RemotingClientProxy::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.0
IL_000a: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_000f: ldstr "http://manchester:9800/Matematik.soap"
IL_0014: call instance void [System.Runtime.Remoting]System.Runtime.Remoting.Services.RemotingClientProxy::ConfigureProxy(class [mscorlib]System.Type,
string)
IL_0019: nop
IL_001a: nop
IL_001b: ret
} // end of method Matematik::.ctor</pre>
<p><strong>RemoteObjects.dll içindeki Matematik sınıfı için Constructor içeriği</strong></p>
<pre class="brush:plain;auto-links:false;toolbar:false" contenteditable="false">.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.MarshalByRefObject::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldstr bytearray (55 00 7A 00 61 00 6B 00 20 00 6E 00 65 00 73 00 // U.z.a.k. .n.e.s.
6E 00 65 00 20 00 79 00 61 00 70 00 31 01 63 00 // n.e. .y.a.p.1.c.
31 01 20 00 6D 00 65 00 74 00 6F 00 64 00 20 00 // 1. .m.e.t.o.d. .
E7 00 61 00 1F 01 31 01 72 00 31 01 6C 00 64 00 // ..a...1.r.1.l.d.
31 01 2E 00 2E 00 2E 00 ) // 1.......
IL_000d: call void [mscorlib]System.Console::WriteLine(string)
IL_0012: nop
IL_0013: nop
IL_0014: ret
} // end of method Matematik::.ctor</pre>
<p><strong>MatMetData.dll içindeki Matematik sınıfı için Toplam metodu içeriği;</strong></p>
<pre class="brush:plain;auto-links:false;toolbar:false" contenteditable="false">.method public hidebysig instance float64
Toplam(float64 deger1,
float64 deger2) cil managed
{
.custom instance void [mscorlib]System.Runtime.Remoting.Metadata.SoapMethodAttribute::.ctor() = ( 01 00 01 00 54 0E 0A 53 6F 61 70 41 63 74 69 6F // ....T..SoapActio
6E 55 68 74 74 70 3A 2F 2F 73 63 68 65 6D 61 73 // nUhttp://schemas
2E 6D 69 63 72 6F 73 6F 66 74 2E 63 6F 6D 2F 63 // .microsoft.com/c
6C 72 2F 6E 73 61 73 73 65 6D 2F 52 65 6D 6F 74 // lr/nsassem/Remot
65 4F 62 6A 65 63 74 73 2E 4D 61 74 65 6D 61 74 // eObjects.Matemat
69 6B 2F 52 65 6D 6F 74 65 4F 62 6A 65 63 74 73 // ik/RemoteObjects
23 54 6F 70 6C 61 6D ) // #Toplam
// Code size 24 (0x18)
.maxstack 3
.locals init ([0] float64 CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld object [System.Runtime.Remoting]System.Runtime.Remoting.Services.RemotingClientProxy::_tp
IL_0007: castclass RemoteObjects.Matematik
IL_000c: ldarg.1
IL_000d: ldarg.2
IL_000e: callvirt instance float64 RemoteObjects.Matematik::Toplam(float64,
float64)
IL_0013: stloc.0
IL_0014: br.s IL_0016
IL_0016: ldloc.0
IL_0017: ret
} // end of method Matematik::Toplamt</pre>
<p><strong>RemoteObjects.dll içindeki Matematik sınıfı için Toplam metodu içeriği;</strong></p>
<pre class="brush:plain;auto-links:false;toolbar:false" contenteditable="false">.method public hidebysig instance float64
Toplam(float64 deger1,
float64 deger2) cil managed
{
// Code size 9 (0x9)
.maxstack 2
.locals init ([0] float64 CS$1$0000)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: add
IL_0004: stloc.0
IL_0005: br.s IL_0007
IL_0007: ldloc.0
IL_0008: ret
} // end of method Matematik::Toplam</pre>
<p>Dikkat ederseniz, üretilen Wrapped Proxy içerisinde SOAP üzerinden HTTP protokolünü kullanarak yapılacak üye çağrıları için gerekli bilgiler yer almaktadır. Şimdi üretilen bu Wrapped Proxy' ı örnek bir istemcide kullanalım. Öncelikle yapmamız gereken SoapSuds ile üretilen Wrapped Proxy' ı istemci uygulamamıza referans etmek olacaktır.</p>
<p><img src="/makale/images/mk164_4.gif" alt="" width="173" height="131" border="0" /></p>
<p><strong>İstemci uygulama;</strong></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using System.Text;
using RemoteObjects;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
Matematik mt = new Matematik();
Console.WriteLine(mt.Toplam(3, 4).ToString());
Console.ReadLine();
}
}
}</pre>
<p>Burada dikkat ederseniz sıradan istemci uygulamalarındaki remoting için gerekli hiç bir konfigurasyon ayarı yoktur. Oysaki kanal bilgisinin (channel) ya da SAO(Server Activated Object) veya CAO (Client Activated Object) için gerekli kayıt işlemlerinin yapılmış olması gerekmektedir. Bunların yapılmayışının nedeni, uzak nesneyi kullanabilmek için gerekli erişim bilgilerinin, SoapSuds ile üretilen Wrapped Proxy içerisinde olmasıdır. Şimdi remote uygulamamızı test edebiliriz. <em>(Aşağıdaki videoyu izleyebilmek için Flash Player gereklidir.)</em></p>
<p><object id="obj1" width="481" height="313" classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" border="0">
<param name="movie" value="http://www.buraksenyurt.com/makale/images/SoapSuds_1.swf" />
<param name="quality" value="High" /> <embed type="application/x-shockwave-flash" width="481" height="313" src="http://www.buraksenyurt.com/makale/images/SoapSuds_1.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" name="obj1" /></object></p>
<p>Görüldüğü gibi, istemci uygulama çalıştığında sunucu üzerinde Matematik sınıfına ait yapıcı metod çalıştırılmıştır. Bu, istemcinin gerçekten sunucu üzerindeki bir referansı kullandığının kanıtıdır. Dahası, sunucuyu çalıştırmadan istemci uygulamayı çalıştırmayı denerseniz, <em>"System.Net.Sockets.SocketException: No connection could be made becaus<br /> e the target machine actively refused it"</em> istisnasını alırsınız ki buda remote sistemin gerçekten tamalandığı anlamına gelir.</p>
<p>Gelelim Non-Wrapped Proxy modeline. Bu modelde, üretilen assembly içerisinde sadece sınıfa ait metadata bilgisi bulunur. Dolayısıyla, Wrapped Proxy' lerde olduğu gibi sadece HTTP protokolüne bağlı değildir. TCP protokolünüde ele alabiliriz. Non-Wrapped Proxy kullanırken istemci tarafında gerekli konfigurasyon ayaları da yapılmalıdır. Bu sayede sunucu üzerinde meydana gelecek kanal ve port değişikliklerini istemci tarafınada yansıtabiliriz. Oysaki Wrapped proxy tipine göre SoapSuds aracı ile metadata' yı içeren assembly' ı yeniden üretmemiz ve dağıtmamız gerekecektir. Yukarıdaki örneğimizi ele aldığımızda, Non-Wrapped Proxy' imizi oluşturmak için SoapSuds aracını aşağıdaki şekilde kullanmamız yeterlidir. SoapSuds aracı yardımıyla Assembly' ın üretilebilmesi için önceden sunucu uygulamanın çalışıyor olması gerektiğini lütfen unutmayınız. Non-Wrapped Proxy üretimi için SoapSuds aracında -nowp anahtarı kullanılır.</p>
<p><strong>Komut :</strong> SoapSuds <strong>-nowp</strong> -url:http://localhost:9800/Matematik.soap?wsdl -oa:MatMetaDataNoWp.dll</p>
<p><img src="/makale/images/mk164_6.gif" alt="" width="640" height="304" border="0" /></p>
<p>Şimdi oluşan MatMetaDataNoWp.dll isimli assembly' ımızı yine ILDASM aracı yardımıyla inceleyelim.</p>
<p><img src="/makale/images/mk164_7.gif" alt="" width="490" height="524" border="0" /></p>
<p>Görüldüğü gibi tek fark Wrapped Proxy' de yer alan get_RemotingReference metodu ile RemotingReference nesnesinin Non-Wrapped Proxy içerisinde olmayışıdır. Dolayısıyla, istemci tarafındaki uygulamamızda gerekli konfigurasyon ayarlarını yapmamız gerekecektir. Bu amaçla istemci tarafına aşağıdaki konfigurasyon dosyasını ekleyelim. Elbette type parametresini belirtirken Assembly adı olarak oluşturulan Non-Wrapped Proxy Assembly' ının adını vermemiz gerekecektir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="Http Client"/>
</channels>
<client>
<wellknown type="RemoteObjects.Matematik,MatMetaDataNoWp" url="http://manchester:9800/Matematik.soap"/>
</client>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Daha sonra ise, yeni proxy assembly' ımızın dll dosyasını istemci uygulamamıza referans etmemiz gerekiyor. <em> ( Önceki örneğimizde üretilen Assembly' da aynı isim alanını ve sınıfı içerdiğinden karşılık olmaması amacıyla MatMetaData.dll referansı bu örnek için kaldırılmıştır.)</em></p>
<p><img src="/makale/images/mk164_8.gif" alt="" width="214" height="162" border="0" /></p>
<p>Şimdi istemcimize ait kodları aşağıdaki gibi değiştirelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">RemotingConfiguration.Configure("..\\..\\App.config",false);
Matematik mt = new Matematik();
Console.WriteLine(mt.Toplam(3, 4).ToString());</pre>
<p>Uygulamamızı test ettiğimizde remoting sisteminin başarılı bir şekilde çalıştığını görebiliriz. Her zamanki gibi uzaktan erişimi ispat etmek için, sunucu uygulamayı çalıştırmadan istemci uygulamayı çalıştırmanızı öneririm. Görüldüğü gibi SoapSuds modelinde Wrapped Proxy ya da Non-Wrapped Proxy' lerin bir birlerine göre temel bazı farklılıkları bulunmaktadır. Son olarak SoapSuds aracı yardımıyla uzak nesne sınıfına ait bir kaynak kodun istemci tarafına taşınabileceğinide berlirtmek istiyorum. Bunun için -gc (Generate Class) anahtarını kullanmak yeterlidir. Örneğin sunucu uygulamamız çalışırken komut satırından aşağıdaki satırı çalıştıralım.</p>
<p><strong>Komut :</strong> SoapSuds -nowp -url:http://localhost:9800/Matematik.soap?wsdl <strong>-gc</strong></p>
<p>Bunun sonucu olarak cs uzantılı bir kaynak kod dosyası oluşur. Dosyanın içeriği aşağıdakine benzer olacaktır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Metadata;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Runtime.InteropServices;
namespace RemoteObjects
{
[Serializable, SoapType(XmlNamespace=@"http://schemas.microsoft.com/clr/nsassem/RemoteObjects/RemoteObjects%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull", XmlTypeNamespace=@"http://schemas.microsoft.com/clr/nsassem/RemoteObjects/RemoteObjects%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull")][ComVisible(true)]
public class Matematik : System.MarshalByRefObject
{
[SoapMethod(SoapAction=@"http://schemas.microsoft.com/clr/nsassem/RemoteObjects.Matematik/
RemoteObjects#Toplam")]
public Double Toplam(Double deger1, Double deger2)
{
return((Double) (Object) null);
}
}
}</pre>
<p>Dolayısıyla istemci tarafından oluşan bu isim alanı ve içeriğini doğrudan kullanabilir yada bu kaynak kod dosyasında bir assembly üretip onu kullanmayı tercih edebiliriz. Tabi böyle bir durumda aynen Non-Wrapped Proxy modelinde olduğu gibi istemci tarafı için gerekli konfigurasyon ayarlarının bildirilmesi gerekmektedir. Böylece geldik bir makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/makale/images/Sample_13_SoapSuds.rar">Örnek Uygulama İçin Tıklayın.</a></p>2006-06-21T12:00:00+00:00.net remotingsoapbsenyurtRemoting mimarisinde, istemci ve sunucu arasında uzak nesneleri paylaşmanın dört farklı yolu vardır. İstemcilerin tek amacı sunucu üzerinde yer alan uzak nesne referanslarını kullanabilmektir. Bu açıdan bakıldığında, istemci uygulamanın uzak sunucu üzerindeki nesne referanslarının yapısını bilmesi gerektiği ortaya çıkmaktadır. Kullanılabilecek yollardan ilki uzak nesne sınıfının bulunduğu paylaşımlı bir assembly' ı tüm istemci uygulamalara dağıtmaktır. Bu istemci uygulamalar için ekstra kod yazmadan kolayca gerçekleştirilebilecek bir işlemdir. Lakin istemci uygulamalarda, uzak sınıfın tüm içeriğinin yer aldığı bir assembly' da mevcuttur. Bu da ILDASM (Intermediate Dis-Assembler Tool) ve başka üçüncü parti araçlar yardımıyla iş mantığının (business logic) istemci tarafından kolayca okunabileceği anlamına gelir. İşte bu dezavnataj nedeni ile özellikle güvenlik açısından çoğu zaman bu teknik tercih edilmez.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=cf435a2e-cd41-4b52-b29d-242aa92607990https://www.buraksenyurt.com/trackback.axd?id=cf435a2e-cd41-4b52-b29d-242aa9260799https://www.buraksenyurt.com/post/-Net-Remoting-SoapSuds-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=cf435a2e-cd41-4b52-b29d-242aa9260799https://www.buraksenyurt.com/post/Server-Side-SponsorShip-bsenyurt-com-danServer Side SponsorShip2006-04-19T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Bir önceki makalemizde Remoting mimarisinde istemci taraflı destek modelini incelemeye çalışmıştık. İstemci taraflı destek modelinin en büyük problemlerinden birisi, istemcilerin firewall arkasında olması halinde ortaya çıkmaktadır. Bu engel, sunucuların istemcilere erişimini kısıtlayacağından istemci taraflı destek modelinin çalışması garanti altına alınmamış olabilir. Bu nedenle, istemcilerin firewall arkasında olup olmadıklarının bilinmediği durumlarda kesinlikle sunucu taraflı destek (server side sponsorship) modeli kullanılmalıdır. Bu makalemizde sunucu taraflı destek modelinin işleyiş şeklinden bahsedecek ve örnek bir uygulama geliştireceğiz.</p>
<p>İlk olarak modelin teorisinden birazda olsa bahsetmekte fayda var. Sunucu taraflı destek modelinde, uzak nesne haricinde bu nesnenin kiralama süresini kontrol eden ve gerektiğinde otomatik olarak uzatan bir destek nesnesi(Sponsor Object) vardır. Yanlız bu sponsor nesne sunucu tarafında olduğu için, istemci tarafından bir şekilde çağırılabilmeli ve kullanılabilmelidir. Dolayısıyla uzak nesnenin kiralama süresini kontrol eden sponsor nesnemizde aslında bir uzak nesnedir. Yani MarshallByRefObject tipinden türetilmiştir. Diğer taraftan bu sponsor nesnenin, uzak nesne referansına ait kiralama süresini, sunucu tarafında kontrol edebilmesi için ayrıca ISponsor arayüzünüde uygulaması gerekmektedir. Bildiğiniz gibi ISponsor arayüzünün sağladığı Renewal metodu ile kiralama süreleri uzatılabilir.</p>
<p>Peki istemci tarafındaki uygulamalar uzak nesnenin kiralama süresini kontrol eden bu sponsor nesnesini nasıl kullanmalıdır? İstemci, uzak nesnesine ait kiralama süresinin ömrünü kontrol edecek uzak sponsor nesnesinide belirli aralıklarla ele alabilmelidir. Bu amaçla, istemci uygulama üzerinde sadece uzak sponsor' u belirli periyotlarla kontrol eden ve ayrı bir thread içerisinde çalışacak başka bir sınıf daha gereklidir. Bu sınıf içerisinde belirli zaman aralıklarında, uzak sponsor nesnesine ait herhangibir üye metod çağırılır. Buradaki amaç, istemci tarafından bir şekilde uzak sponsor nesnesini aktif olarak tutmaktır. Nitekim, uzak nesne kiralama süresinin yönetecek olan referans sunucu üzerinde duran sponsor nesne referansıdır.</p>
<p>Model biraz karışık görünebilir. Ancak örneğimizi geliştirirken çok daha net anlaşılabileceğini düşünmekteyim. Dilerseniz hiç vakit kaybetmeden örneğimizi geliştirelim. İşe hem sunucu hemde istemci uygulamamızın ortak olarak kullanacağı class library' yi tasarlamakla başlayalım. Bu kütüphane içerisinde, hem uzak nesnemiz, hem de uzak sponsor nesnemiz için gerekli interface tanımlamalarını yapacağız.</p>
<p><img src="/makale/images/mk157_1.gif" alt="" width="447" height="218" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Runtime.Remoting.Lifetime;
namespace RemoteFace
{
public interface IRemoteObject
{
double Toplam(double x, double y);
}
public interface ISponsorObject:ISponsor
{
void CanliKal();
}
}</pre>
<p>IRemoteObject isimli arayüzümüz (interface), uzak nesnemiz için gerekli prototipi sunmaktadır. Bu kütüphanede asıl önemli olan arayüz ise ISponsorObject arayüzümüzdür. Bu arayüzümü ayrıca ISponsor arayüzünden de türettik. Böylece sponsor nesnemizin hem ISponsorObject arayüzünü uygulamasını hem de, kiralama yönetimi için gerekli olan ve ISponsor arayüzünden gelen Renewal metodunu uygulamasını sağlamış olacağız. Burada özellikle interface' leri kullanmamızın nedeni bildiğiniz gibi, istemci uygulamanın sunucu tarafındaki uzak nesnelerin sağladığı metodlarda olacak değişikliklerden etklilenmemesini sağlamaktır. Öyleki biz istemci tarafında bu arayüzleri kullanarak uzak nesne ve sponsorumuza ait referansları çağırabileceğiz. Polimirfizim (Polymorphsym) sağolsun. Gelelim sunucu tarafına. Sunucu tarafımızdaki uygulamamızda uzak nesnemizi ve uzak sponsor nesnemizi aşağıdaki gibi oluşturacağız.</p>
<p><img src="/makale/images/mk157_2.gif" alt="" width="474" height="318" border="0" /></p>
<p>Uzak Nesne Sınıfımız;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">class RemoteObj:MarshalByRefObject,IRemoteObject
{
public RemoteObj()
{
Console.WriteLine("Uzak nesne örneği oluşturuldu " + DateTime.Now.ToString());
}
#region IRemoteObject Members
public double Toplam(double x, double y)
{
return x + y;
}
#endregion
}</pre>
<p>Uzak Sponsor Sınıfımız;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">class ServerSponsor:MarshalByRefObject,ISponsorObject
{
public ServerSponsor()
{
Console.WriteLine("Uzak sponsor nesne oluşturuldu " + DateTime.Now.ToString());
}
#region ISponsorObject Members
public void CanliKal()
{
Console.WriteLine("Canli kal metodu çağırıldı " + DateTime.Now.ToString());
}
#endregion
#region ISponsor Members
public TimeSpan Renewal(System.Runtime.Remoting.Lifetime.ILease lease)
{
Console.WriteLine("Uzak nesne için kiralama süresi yenilendi " + DateTime.Now.ToString());
return TimeSpan.FromSeconds(6);
}
#endregion
}</pre>
<p>Uzak nesne sınıfımızdan ziyade, uzak sponsor nesne sınıfımızın işleyişi bizim için çok daha önemlidir. Dikkat ederseniz, sponsor sınıfımızın içerisinde bir iş yapmayan CanliKal isimli bir metod vardır. Bu metodu istemci tarafında yer alan başka bir sınıfımız kullanacak. Bunu biraz sonra açıklamakta fayda var. Sponsor sınıfımızın Renewal metodu kiralama süresini 6 saniye kadar uzatıyor. Peki bu kimin kiralama süresi? İşte istemci tarafında yer alacak kodlarımızda, bu sponsor nesnesinin ele alacağı Lease Manager' ı seçerken, uzak nesnenin kiralama yöneticisini ele alıp sponsor nesnemize göndereceğiz. Bir başka deyişle, uzak nesnemizin kiralama yöneticisine, sponsor nesnemizi register edeceğiz. Böylece uzak nesnenin kiralama süresini, sunucu üzerindeki sponsor nesne örneğimiz üstlenmiş olacak. Vakit kaybetmeden sunucu uygulamamızın kodlarını ve konfigurasyon dosyasını aşağıdaki gibi geliştirelim.</p>
<p>Server;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
RemotingConfiguration.Configure(@"..\\..\\ServerApp.config",true);
Console.WriteLine("Sunucu dinlemede...");
Console.ReadLine();
}</pre>
<p>ServerApp.config</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="4378">
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
</channel>
</channels>
<service>
<wellknown type="Server.RemoteObj,Server" objectUri="RemObj" mode="Singleton"/>
<wellknown type="Server.ServerSponsor,Server" objectUri="RemSpn" mode="Singleton"/>
</service>
<lifetime leaseTime="6" renewOnCallTime="2" leaseManagerPollTime="1"/>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Dikkat ederseniz, hem uzak nesnemiz hemde sponsor nesnemiz için ayrı ayrı SAO (Server Activated Object) tipinde ve Singleton modeline uygun tanımlamalar yapıyoruz. Sunucu üzerinde çalışacak uzak nesnelerimiz için geçerli kiralama sürelerinide lifetime boğumunda (node) belirtmekteyiz. Elbette, buradaki kiralama süreleri tüm referanslar için geçerli olacaktır. Yani hem uzak nesnemiz hemde sponsor nesnemiz için. Dilerseniz bu referansların kiralama sürelerini ayrı ayrıda tanımlayabilirsiniz. Bunun için tek yapmanız gereken InitializeLifetimeService metodunu uzak nesne sınıfları içerisinde override etmektir.</p>
<p>Gelelim istemci tarafındaki kodlara. Sunucu taraflı sponsor kullanımına ait teoriden bahsederken, istemci tarafında sunucu üzerindeki sponsor referansını düzenli olarak tetikleyecek bir sınıf olacağından bahsetmiştik. İşte bu sınıfımızı istemci uygulamamızda aşağıdaki gibi geliştireceğiz.</p>
<p><img src="/makale/images/mk157_3.gif" alt="" width="305" height="223" border="0" /></p>
<p>PollingObject</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">class PollingObject
{
private bool _canliBirak;
private ISponsorObject _sponsorObject;
public bool CanliBirak
{
get { return _canliBirak; }
set { _canliBirak = value; }
}
public PollingObject(ISponsorObject sponsorObject)
{
_canliBirak = true;
_sponsorObject = sponsorObject;
Thread currTrd=new Thread(this.CanliTut);
currTrd.Start();
}
public void CanliTut()
{
while (CanliBirak)
{
_sponsorObject.CanliKal();
Thread.Sleep(2000);
}
}
}</pre>
<p>PollingObject isimli sınıfımızın en büyük özelliği, örneği oluşturulurken parametre olarak ISponsorObject tipinden bir nesne alması. Bu çalışma zamanında bizim oluşturacağımız uzak sponsor nesne örneğimiz (ServerSponsor) olacaktır. Basit olarak yapıcı metod bu nesne örneğini kullanacak CanliTut isimli metodu, ayrı bir thread içerisinde ve CanliBirak isimli özellik değeri true olduğu müddetçe, çağıracaktır. Bu metodun çağırılması ile, istemci tarafından kullanılan uzak nesneye ait kiralama süresinin, sunucu üzerindeki sponsor nesne örneği tarafından kontrol altına alınması sağlanmış olunur. İşleyişi istemci uygulamamızın kodları çok daha iyi anlatmaktadır.</p>
<p>Client</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
RemotingConfiguration.Configure("..\\..\\ClientApp.config", true);
IRemoteObject remObj = (IRemoteObject)Activator.GetObject(typeof(IRemoteObject), "tcp://manchester:4378/RemObj");
#region Server Side Sponsor Kullanılmaya Başlanır
ISponsorObject spnObj = (ISponsorObject)Activator.GetObject(typeof(ISponsorObject), "tcp://manchester:4378/RemSpn");
PollingObject pllObj = new PollingObject(spnObj);
ILease il = (ILease)((MarshalByRefObject)remObj).GetLifetimeService();
il.Register(spnObj);
#endregion
for (int i = 0; i < 8; i++)
{
Console.WriteLine(remObj.Toplam(i, i + 1).ToString());
System.Threading.Thread.Sleep(4000);
}
Console.WriteLine("Metodlar sonlandırıldı...");
il.Unregister(spnObj);
pllObj.CanliBirak = false;
Console.WriteLine("Programı kapatmak için bir tuşa basın...");
Console.ReadLine();
}</pre>
<p>İlk olarak uzak nesnemizi (RemoteObject) kullanabilmemizi sağlayacak IRemoteObject referansı elde edilir. Ardından aynı yol ile ISponsorObject referansı elde edilir. Sonrasında ise PollingObject tipimize ait bir nesne örneğini oluşturuyoruz. İşte bu andan itibaren, parametre olarak gönderdiğimiz spnObj arayüzü ile sunucu üzerindeki sponsor nesne referansını kullanmaya başlıyoruz. İzleyen satırda, uzak nesne örneğini referans eden remObj' nin kiralama yöneticisini ILease arayüzüne atıyoruz. İşte can alıcı nokta burası. ILease referansına, sunucu üzerinde yer alan sponsor nesnemizi kayıt ediyoruz. Dolayısıyla, PollingObject içerisinde ayrı bir iş parçacığı olarak çalışan CanliTut isimli metod 2 saniyelik aralıklarla uzak sponsor nesne referansının CanliKal metodunu çağırmaya başlıyor. Bu çağırılar sonucu uzak nesnenin kiralama süreside, ILease referansını unregister edip, CanliTut metodunun işleyişini CanliBirak isimli özelliğe false değerini atayıp kesinceye kadar, uzamaya devam ediyor. Kısacası, istemcinin kullandığı uzak nesnenin kiralama süresinin yönetimini, sunucu üzerinde yer alan ve istemci tarafından belirli periyotlarla kontrol edilen uzak sponsor nesne referansına devretmiş oluyoruz. Uygulamamızı test etmeden önce, istemci tarafındaki konfigurasyon dosyasınıda aşağıdaki gibi oluşturalım.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp">
<clientProviders>
<formatter ref="binary" />
</clientProviders>
</channel>
</channels>
<client>
<wellknown type="RemoteFace.IRemoteObject,RemoteFace" url="tcp://manchester:4378/RemObj/"/>
<wellknown type="RemoteFace.ISponsorObject,RemoteFace" url="tcp://manchester:4378/RemSpn/"/>
</client>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Şimdi olayı iyice analiz edebilmek için client tarafındaki kodlarımızda sponsor nesne ile ilgili olan kısımları kaldırıp çalıştıracağız.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
RemotingConfiguration.Configure("..\\..\\ClientApp.config", true);
IRemoteObject remObj = (IRemoteObject)Activator.GetObject(typeof(IRemoteObject), "tcp://manchester:4378/RemObj");
for (int i = 0; i < 8; i++)
{
Console.WriteLine(remObj.Toplam(i, i + 1).ToString());
System.Threading.Thread.Sleep(4000);
}
Console.WriteLine("Metodlar sonlandırıldı...");
Console.WriteLine("Programı kapatmak için bir tuşa basın...");
Console.ReadLine();
}</pre>
<p>Kullandığımız uzak nesne örneğini SAO olarak Singleton modunda tasarlamıştık. Bununla birlikte uzak nesne için varsayılan kiralama sürelerinide belirtmiştik. İstemci tarafı peş peşe uzak nesne metodlarını çağırdığında, her kiralama süresi sonlandıktan sonra sunucu üzerinde yeni bir referansın oluşturulmuş olması gerekmektedir. Yani yapıcı metodların birden fazla kez çağırılması durumu söz konusudur.</p>
<p><img src="/makale/images/mk157_4.gif" alt="" width="498" height="563" border="0" /></p>
<p>Gördüğünüz gibi, uzak nesne örneğine ait kiralama süreleri sona erdikçe yeni uzak nesne referansları sunucu üzerinde oluşturulmuştur. Ancak Sponsor kodlarımızı tekrardan uygulamaya dahil edersek aşağıdaki sonuçları elde ederiz.<em>(Aşağıdaki ekran görüntüsü flash formatında olup, flash player yüklemenizi gerektirebilir...)</em></p>
<p><object id="obj1" width="509" height="573" classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" border="0">
<param name="movie" value="http://www.buraksenyurt.com/makale/images/ServerSponsor2.swf" />
<param name="quality" value="High" /> <embed type="application/x-shockwave-flash" width="509" height="573" src="http://www.buraksenyurt.com/makale/images/ServerSponsor2.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" name="obj1" /></object></p>
<p>Bu sefer, uzak nesne örneğimize ait tek bir referans tüm uygulama boyunca yaşamaktadır. Çünkü uzak sponsorumuz kiralama sürelerini otomatik olarak yenilemektedir. Sunucu taraflı destek kontrolü uygulanış açısından zor görünsede istemci taraflı destek modelinin bazı dezavantajlarını ortadan kaldırmaktadır. Örneğin FireWall engellerini. Bu yüzdende remoting uygulamalarında sıkça tercih edilen bir yöntemdir. Böylece geldik bir makalemizin daha sonuna bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/makale/images/ServerSideSponsors.rar">Örnek kod için tıklayınız.</a></p>2006-04-19T12:00:00+00:00.net remotingbsenyurtBir önceki makalemizde Remoting mimarisinde istemci taraflı destek modelini incelemeye çalışmıştık. İstemci taraflı destek modelinin en büyük problemlerinden birisi, istemcilerin firewall arkasında olması halinde ortaya çıkmaktadır. Bu engel, sunucuların istemcilere erişimini kısıtlayacağından istemci taraflı destek modelinin çalışması garanti altına alınmamış olabilir. Bu nedenle, istemcilerin firewall arkasında olup olmadıklarının bilinmediği durumlarda kesinlikle sunucu taraflı destek (server side sponsorship) modeli kullanılmalıdır. Bu makalemizde sunucu taraflı destek modelinin işleyiş şeklinden bahsedecek ve örnek bir uygulama geliştireceğiz.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=2a7967db-28d9-4bd0-989e-190f3b96c0b30https://www.buraksenyurt.com/trackback.axd?id=2a7967db-28d9-4bd0-989e-190f3b96c0b3https://www.buraksenyurt.com/post/Server-Side-SponsorShip-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=2a7967db-28d9-4bd0-989e-190f3b96c0b3https://www.buraksenyurt.com/post/Client-Side-SponshorShip-bsenyurt-com-danClient Side SponshorShip2006-04-12T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Son makalemizde, remoting uygulamalarında uzak nesnelere ait kiralama sürelerinin (Lease Time) nasıl yönetilebileceğinden bahsetmiştik. Bununla birlikte bir uzak nesnenin kiralama süresinin sonlamasının ardından gelecek olan metod çağrılarında istemcilerin olmayan bir referansa erişmeye çalıştığını ve bu nedenlede çalışma zamanı istisnaları ile karşılaşabileceklerini görmüştük. Bu makalemizde, kiralama sürelerini otomatik olarak uzatmak için istemci taraflı destek modelinden (Client Side sponsorShip) nasıl yararlanabileceğimizi incemeleye çalışacağız.</p>
<p>SponsorShip mimarisi temel olarak, uzak nesnelerin yaşam sürelerini otomatik olarak arttırmak için kullanılır. İki şekilde uygulanabilir. Bunlardan birisi istemci tarafında diğeri ise sunucu tarafında yapılabilen destekleme sistemidir. Her iki destek türününde birbirlerine göre avantajları ve dezavantajları vardır. İstemci taraflı destek modelinde (Client Side Sponsorship), istemcinin kullandığı uzak nesnenin kiralama yöneticisi (Lease Manager) ile, ISponsor arayüzünden türetilen bir sınıfın iş birliği söz konusudur.</p>
<p>Bu işbirliğinin bir sonucu olarak, uzak nesneye ait referansın yaşam süresini doldurması halinde, istemci taraflı sponsor otomatik olarak devreye girecek ve kiralama süresini uzatacaktır. Bu modelin çalışabilmesi için, sunucudan gelen geri bildirimlerin(Callbacks) istemci tarafından ele alınabilmesi gerekmektedir. Bu da istemcinin yeri geldiğinde sunucu isteklerini kabul eden bir davranış sergilemesi demektir. İşte bu nedenle, özellikle firewall gibi güveli sistemlerin arkasında kalan istemcilere sunucunun erişememesi halinde istemci taraflı destek modeli bir işe yaramayacaktır. Bu istemci taraflı destek sistemi açısından bir dezavantaj olarak görülebilir.</p>
<p>Peki istemci taraflı modeli nasıl uygulayacağız? Bunu anlamanın en iyi yolu basit bir örnek üzerinden gitmek ile olacaktır. Teorik olarak yapmak istediğimiz şey, istemcilerin kullandığı uzak nesnelere ait kirlama sürelerini otomatik olarak arttırabilmek ve böylece çalışma zamanında meydana gelecek kayıp referans çağrılarının önüne geçebilmektir. İlk olarak uzak nesnemizi geliştirmekle işe başlayalım. Uzak nesnemizin aşağıda görülen modele sahip olduğunu düşünelim.</p>
<p><img src="/makale/images/mk156_1.gif" alt="" width="207" height="199" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public class RemoteObj : MarshalByRefObject
{
public RemoteObj()
{
Console.WriteLine("Uzak nesne yapıcı metodu çağırıldı...");
}
public int GetTotal(int orderID)
{
return orderID * 100;
}
}</pre>
<p>Şimdi vakit kaybetmeden sunucu uygulamamızıda aşağıdaki gibi geliştirelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
RemotingConfiguration.Configure("..\\..\\ServerApp.config",true);
Console.WriteLine("Sunucu dinlemede...Kapatmak için bir tuşa basın...");
Console.ReadLine();
}</pre>
<p>Sunucu uygulamamıza ait remoting ayarlarını bir konfigurasyon dosyasında tutacağız. Dikkat ederseniz, kiralama süresini mümkün olduğunca kısa tutmaya çalıştık. Uzak nesneye ait bir referans oluşturulduktan sonra yaklaşık olarak 3 saniyelik bir ömrü olacaktır. Diğer taraftan remoting mimarimizi CAO (Client Activated Object) modelini baz alarak geliştirdik. Bu nedenle istemci tarafında bir uzak nesne örneği oluşturulur oluşturulmaz, sunucu üzerinde bu nesneye bağlı bir referans hemen oluşturulacaktır.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<service>
<activated type="RemoteLib.RemoteObj,RemoteLib"/>
</service>
<lifetime leaseTime="3" renewOnCallTime="1" leaseManagerPollTime = "1" />
<channels>
<channel ref="tcp" port="4567">
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Bu konfigurasyon dosyasında standart ayarların yanında özellikle channel boğumu içerisinde yer alan serverProviders ve clientProviders isimli alt boğumlar hemen göze çarpmaktadır. Bu alt boğumlar aynen istemci tarafındada kullanılmak zorundadır.</p>
<table id="table58" style="width: 100%;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffff">
<tbody>
<tr>
<td width="53"><img src="/makale/images/dikkat.gif" alt="" width="53" height="53" border="0" /></td>
<td><em>Konfigurasyon dosyasında serverProviders ve clientProviders boğumlarını kullanmassak (ki istemci destek modelinde bunları hem istemci hem sunucu konfigurasyon dosyalarında kullanmalıyız) güvenlik ile ilgili bir çalışma zamanı hatasını aşağıdaki gibi alırız. <br /> <br /> </em><img src="/makale/images/mk156_4.gif" alt="" width="402" height="66" border="0" /></td>
</tr>
</tbody>
</table>
<p><br />Gelelim istemci uygulamamıza. İstemci uygulamamızı ilk olarak aşağıdaki gibi herhangibir destek nesnesi (sponsor object) olmadan geliştireceğiz. İstemci uygulamamız basit olarak, uzak nesneye ait bir nesne örneğini client activated object modelinde oluşturmaktadır. Daha sonra istemci, uzak nesne referansını kullanarak GetTotal isimli metodu arka arkaya 10 defa çağırmaktadır. Bu metod çağırımlarının her birinde istemci uygulama yaklaşık olarak 3 saniye süreyle uyutulmaktadır. Dolayısıyla bu gecikmeler, uzak referansın kiralama süresinin dolmasına ve bu süre dolmadan metod çağırımlarının tamamlanamamasına neden olacaktır. İşte buda bizim sponsor yönetimine gitmemizi sağlayacak etkendir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
RemoteObj rm = null;
try
{
RemotingConfiguration.Configure("..\\..\\ClientApp.config", true);
rm = new RemoteObj();
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i+"nci çağrı..."+rm.GetTotal(i).ToString());
System.Threading.Thread.Sleep(3000);
}
}
catch (Exception err)
{
Console.WriteLine(err.Message);
}
finally
{
}
Console.WriteLine("Programı kapatmak için bir tuşa basın...");
Console.ReadLine();
}</pre>
<p>İstemci uygulamamıza ait konfigurasyon dosyası ise aşağıdaki gibidir. Dikkat ederseniz, channel bilgisinde tcp tipini ve 0 numaralı bir portu hizmete sunduğumuzu görüyorsunuz. Port bilgisinin 0 olması, bir sunucunun bu istemciye bağlanmaya çalışması sırasında, uygun olan boş portlardan birinin sunucuya hizmet için tahsis edilmesini sağlar. Burada böyle bir channel tipi kullanmamızın tek nedeni, istemcinin destek modelini kullanabilmesini sağlamaktır. Nitekim bu modelde, sunucu uygulama, istemci tarafına geri bildirimlerde bulunabilmelidir. Buda istemcinin yeri geldiğinde sunucu gibi davranmasını gerektirir ki bu ancak uygun bir portun sunucuya verilmesi ile gerçekleşebilir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<client url="tcp://manchester:4567">
<activated type="RemoteLib.RemoteObj,RemoteLib"/>
</client>
<channels>
<channel ref="tcp" port="0">
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>İstemci uygulamamızı bu haliyle test ettiğimizde çalışma zamanında daha ikinci metod çağırımına geçemeden aşağıdaki ekranda görülen hata mesajı ile karşılaşırız.</p>
<p><img src="/makale/images/mk156_3.gif" alt="" width="638" height="96" border="0" /></p>
<p>Bu hatanın nedeni son derece açıktır. Uzak nesneye ait referansın kiralama süresi (Lease Time) dolduğu için istemci uygulamamız, çalışma zamanında olmayan bir referansa ait kayıp metod çağırılarında bulunmaktadır. O halde artık, destek modelini kullanarak bu hatanın önüne nasıl geçebileceğimize bakabiliriz. İlk olarak istemci taraflı destek mimarisini (Client Side SponsorShip) kullandığımız için, istemci tarafında bir takım değişiklikler yapmamız gerekecektir. Bunlardan birincisi, sponsor hizmetini kullanacak olan bir sınıfın tasarlanmasıdır. Bu sınıfı aşağıdaki gibi geliştirdiğimizi düşünebiliriz.</p>
<p><img src="/makale/images/mk156_2.gif" alt="" width="276" height="228" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">class ClientSponsor : MarshalByRefObject, ISponsor
{
#region ISponsor Members
public TimeSpan Renewal(ILease lease)
{
Console.WriteLine("Sponsor süre yenileme metodu çalıştırıldı.");
return TimeSpan.FromSeconds(5);
}
#endregion
}</pre>
<p>Dikkat ederseniz, istemci taraflı bir sponsor nesnesi MarshalByRefObject ile ISponsor tiplerinden türer. ISponsor tipi, Renewal isimli bir metod sunar. Bu metodun geri dönüş tipi TimeSpan türünden bir süredir ve sponsor nesnesinin ilişkilendirildiği uzak nesne referansının yeni kiralama süresini belirtmektedir. Bu metod Lease Manager ile konuşabilmek için parametre olarak ILease arayüzü tipinden bir nesneyi kullanır.</p>
<p>Örneğimizde kiralama süresini 5 saniye kadar uzatıyoruz. Dolayısıyla, uzak nesne refaransına ait kiralama süresinin sonlanması halinde oluşacak kayıp metod çağırılarının da önüne geçmiş oluyoruz. Ancak henüz işimizi tamamlamış değiliz. Yazmış olduğumuz bu sınıfın görevini yerine getirebilmesi için, çalışma zamanında güncel Lease Manager' a kayıt edilmesi (register) gerekmektedir. Kaydetme işleminin tam tersi olan unregister işlemi ise, sponsor nesnesi ile Lease Manager' ın ortaklığını kesen bir davranış gösterir. İstemci uygulamamızın client side sponsor sınıfını kullanacak yeni hali aşağıdaki gibi olmalıdır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
ILease il=null;
ClientSponsor cs=null;
RemoteObj rm = null;
try
{
RemotingConfiguration.Configure("..\\..\\ClientApp.config", true);
rm = new RemoteObj();
#region Sponsor register edilir.
il = (ILease)rm.GetLifetimeService();
cs = new ClientSponsor();
il.Register(cs);
#endregion
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i+"nci çağrı..."+rm.GetTotal(i).ToString());
System.Threading.Thread.Sleep(3000);
}
}
catch (Exception err)
{
Console.WriteLine(err.Message);
}
finally
{
il.Unregister(cs);
}
Console.WriteLine("Programı kapatmak için bir tuşa basın...");
Console.ReadLine();
}</pre>
<p>Sponsor sınıfımıza ait nesne örneğini çalışma zamanında, istemci tarafından kullanılan uzak nesne referansına ait Lease Manager ile ilişkilendirebilmek için yine güncel Life Time Servisini elde etmemiz gerekir. Bunun sonucu olarak oluşan ILease arayüzü tipini kullanarak sponsor nesnemizi Lease Manager için kayıt edebiliriz.(Register) Uygulamamızı şimdi bu haliyle çalıştıracak olursak hiç bir problemle karşılaşılmadığını görürüz. Dikkat ederseniz belirli zaman aralıklarında kiralama süreleri sona ermeden otomatik olarak uzatılmaktadır.</p>
<p><object id="obj1" width="425" height="453" classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" border="0">
<param name="movie" value="http://www.buraksenyurt.com/makale/images/ClienSponsor1.swf" />
<param name="quality" value="High" /> <embed type="application/x-shockwave-flash" width="425" height="453" src="http://www.buraksenyurt.com/makale/images/ClienSponsor1.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" name="obj1" /></object></p>
<p>Tüm metodlar çalıştırılmasını tamamladıktan sonra, finally bloğu içerisinde sponsor sınıfımıza ait nesne örneğide unregister edilerek Lease Manager ile olan işbirliğine son verilmektedir. Görüldüğü gibi istemci taraflı destek modeli ile, kiralama süreleri sona ermiş olan referansların yol açacağı kayıp metod çağırımlarının önüne geçebilir ve uygulamanın devamlılığını sağlayabiliriz. İstemci taraflı bu modelin dışında bir de sunucu taraflı bir destek modeli olduğundan bahsetmiştik. (Server Side Sponsorship) Bu modelide bir sonraki makalemizde incelemeye çalışacağız. Böylece geldik bir makalemizin daha sonuna bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/makale/images/ClientSponsor.rar">Örnek kod için tıklayınız.</a></p>2006-04-12T12:00:00+00:00.net remotingbsenyurtSon makalemizde, remoting uygulamalarında uzak nesnelere ait kiralama sürelerinin (Lease Time) nasıl yönetilebileceğinden bahsetmiştik. Bununla birlikte bir uzak nesnenin kiralama süresinin sonlamasının ardından gelecek olan metod çağrılarında istemcilerin olmayan bir referansa erişmeye çalıştığını ve bu nedenlede çalışma zamanı istisnaları ile karşılaşabileceklerini görmüştük. Bu makalemizde, kiralama sürelerini otomatik olarak uzatmak için istemci taraflı destek modelinden (Client Side sponsorShip) nasıl yararlanabileceğimizi incemeleye çalışacağız.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=21161dae-efed-4f73-8a93-d25b5942dbd10https://www.buraksenyurt.com/trackback.axd?id=21161dae-efed-4f73-8a93-d25b5942dbd1https://www.buraksenyurt.com/post/Client-Side-SponshorShip-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=21161dae-efed-4f73-8a93-d25b5942dbd1https://www.buraksenyurt.com/post/-Net-Remoting-Lease-Time-(Kiralc4b1k-Sure)-Yonetimi-bsenyurt-com-dan.Net Remoting - Lease Time (Kiralık Süre) Yönetimi2006-04-06T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Remoting mimarisi göz önüne alındığında dikkat çekici noktalardan bir tanesi, sunucu tarafında oluşturulan uzak nesnelerin (remote object) yaşam süreleridir. İstemciler, uzak nesnelere ait referansları kullanırken bunların yaşam sürelerini sunucu tarafındaki konfigurasyon belirler. Bu istemcilerin sunucu tarafındaki referanslara ait kaynaklara açıkça müdahale edememesinin de bir sonucu olarak görülebilir. Sunucu tarafında yapılan bu yaşam sürelerinin yönetimine kısaca Kiralık Süre Yönetimi (Lease Time Management) denmektedir. Bu makalemizde kısaca bu konuyu incelemeye çalışacağız.</p>
<p>Bir istemci, uzak nesneye ait bir referans oluşturduğunda sunucu tarafında bu referans için bir geri sayım süresi başlatılır. Buna çoğunlukla <strong>Initial Lease Time</strong> (Başlangıç Kiralama Süresi) denir. Bu süre geriye doğru hareket eder ve sunucu tarafında çalışan <strong>Lease Manager </strong>yardımıyla belirli aralıklarla (varsayılan olarak 10 saniyede 1) kontrol edilir. Eğer bir referansın geriye doğru işleyen kiralama süresi sonlanırsa (ki bu o anki sürenin 0 olması anlamına gelir), garbage collector tarafından toplanılmak üzere işaretlenir. İşte bu andan sonra istemci, aynı referansa ait bir üyeyi çağırdığında çalışma zamanında bir exception ile karşılaşır. Bunun sebebi istemci tarafından oluşturulan uzak nesnenin sunucu üzerindeki kiralama süresinin sıfırlanmış bir başka deyişle yaşam süresinin bitmiş olması ve bu nesneye ait referansın artık sunucuda bulunamayışıdır.</p>
<p>Başlangıçta bir uzak nesnenin <strong>InitialLeaseTime</strong> süresi 300 saniyedir. Yani 5 dakika kiralama süresi söz konusudur. İstemcileri var olmayan bir referansa ait metodları çağırmaları halinde karşılaşacakları exception' lardan korumanın çeşitli yolları vardır. Bunlardan birisi uzak nesneye ait <strong>RenewOnCallTime</strong> özelliğinin değeridir. Bu değere verilen süre, bir uzak nesne referansının Lease Time süresi dolmadan önce, istemci tarafından gelebilecek bir metod çağırımının ele alınmasında önemli rol oynamaktadır. Bunu şöyle açıklayabiliriz. Bir uzak nesnenin kiralama süresinin 6 saniye olduğunu ve RenewOnCallTime süresininde 2 saniye olduğunu düşünelim. İstemci uzak nesneye ait bir referansı ilk oluşturduğunda, kiralama süresi geriye doğru azalmaya başlayacaktır. Sunucu üzerindeki güncel kiralama süresi (Current Lease Time) 2 saniyeye geldiğinde, eğer istemci tarafından bir metod çağırısı daha yapılırsa, nesnenin kiralama süresi otomatik olarak RenewOnCallTime' da belirtilen süreye ayarlanır. Bu durumda bu süre 2 saniye olacaktır. RenewOnCallTime süresinin işleyişini örneklerimizde daha yakından analiz edeceğiz ve daha kolay anlayacağız.</p>
<p>Uzak nesnelere ait referansların yaşam sürelerini istersek değiştirebiliriz. Bunu gerçekleştirebilmek için uzak nesneye ait kalıtım yolu ile gelen <strong>InitializeLifeTimeService</strong> isimli metodu override (ezmek) etmemiz gerekecektir. Bu metod temel olarak uygulandığı tipe ait kiralama sürelerinin yönetiminin sağlanmasından sorumludur. Buradaki ayarlamalar yardımıyla bir uzak nesne referansının InitialLeaseTime ve RenewOnCallTime sürelerini ayarlayabiliriz. Hatta referansın sonsuza dek (elbetteki çevre koşulları uygun olduğu sürece) yaşamasınıda sağlayabiliriz.</p>
<table id="table40" style="width: 100%;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffff">
<tbody>
<tr>
<td width="53"><img src="/makale/images/dikkat.gif" alt="" width="53" height="53" border="0" /></td>
<td><em>Kiralama sürelerinin (Lease Time) yönetimi sadece Client Activated Object' ler için ve Server Activated Object' lerdede sadece Singleton modeli için geçerlidir. Yani SingleCall için kiralama süreleri uygulanamaz. Nitekim SingleCall modelinde uzak nesne referansları metod çağırımlarından sonra zaten yok edilirler. </em></td>
</tr>
</tbody>
</table>
<p><br />Şimdi kiralama sürelerini yönetebileceğimiz basit bir örnek ile konumuzun derinlerine inmeye çalışalım. İlk olarak RenewOnCallTime süresinin sağladığı etkiyi incelemeye çalışacağız. Sunucu tarafımızda yer alacak uzak nesne modelinde, kiralama sürelerini yöneteceğiz ve ardından istemci tarafında bu nesneye ait örneklemelerin ve üye çağırımlarının etkilerini incelemeye çalışacağız. Model olarak işimizi kolaylaştırması açısından Client Activated Object tipinden uzak nesneler kullanacağız. İlk olarak uzak nesnemizi aşağıdaki gibi oluşturalım.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public class RemoteObj : MarshalByRefObject
{
public string Info(string prm)
{
return "Remote Metod " + prm;
}
public RemoteObj()
{
Console.WriteLine("Nesne oluşturuldu...");
}
public override object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromSeconds(6);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}
}</pre>
<p>Uzak nesnemizi incelediğimizde bizim için belkide en önemli metod override edilmiş olan InitializeLifeTimeService' dır. Peki bu ezme işlemi ile ne yapıyoruz biz? Bu metod tam olarak çalışma zamanında bir uzak nesnenin ilk oluşturulduğu sırada, sadece o nesne örneğine ait referans için geçerli olacak kiralama sürelerini belirlemektedir. Örneğin buradaki değerlere göre referans 6 saniye boyunca sunucu üzerinde kiralanacaktır. Eğer nesnenin ömrünün bitmesine 2 saniye kaldığında, bu son süre içerisinde de bir metod çağırımı gerçekleşirse kiralama süresi RenewOnCallTime' da belirtildiği üzere 2 saniyeye set edilecektir. Nesnemizin bu yaşam süreleri ile kullanışını incelemek amacıyla sunucu ve istemci tarafındaki kodlarımızı aşağıdaki gibi geliştirelim.</p>
<p>Sunucu;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
TcpServerChannel srvC = new TcpServerChannel(4500);
ChannelServices.RegisterChannel(srvC,true);
RemotingConfiguration.RegisterActivatedServiceType(typeof(RemoteObj));
LifetimeServices.LeaseManagerPollTime=TimeSpan.FromSeconds(1);
Console.WriteLine("Server dinlemede...");
Console.ReadLine();
}</pre>
<p>Sunucu tarafında yer alan kodlarımızda, LeaseManager için LeaseManagerPollTime süresini 1 saniye olarak ayarlamaktayız. Bu, LeaseManager' ın her bir saniyede, sunucu üzerindeki uzak nesne referanslarının kiralama sürelerini kontrol edeceği anlamına gelmektedir.</p>
<p>İstemci;</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
try
{
TcpClientChannel cliC = new TcpClientChannel();
ChannelServices.RegisterChannel(cliC, true);
RemotingConfiguration.RegisterActivatedClientType(typeof(RemoteObj), "tcp://manchester:4500/");
RemoteObj rmo = new RemoteObj();
for (int i = 1; i < 6; i++)
{
Console.WriteLine(rmo.Info("Test " + i.ToString()));
ILease currLease = (ILease)rmo.GetLifetimeService();
Console.WriteLine(currLease.CurrentLeaseTime.ToString());
System.Threading.Thread.Sleep(2000);
}
}
catch (System.Exception err)
{
Console.WriteLine(err.Message);
}
Console.ReadLine();
}</pre>
<p>İstemci tarafında yaptıklarımıza gelince. Burada uzak nesneye ait örnek oluşturulduktan sonra, bu referansa ait Info isimli metod arka arkaya 6 kez çalıştırılmaktadır. Her bir metod çağırımından sonra uzak nesne referansının sunucu üzerinde kalan kiralama süresi ömrü istemci tarafındaki Console penceresine yazılmaktadır. Daha sonrasında ise process 2 saniye kadar uyutulur. Şimdi uygulamanın çalışmasını izleyelim. <em>(Aşağıdaki video görüntüsü flash formatında olup bilgisayarınıza flash player kurmanızı gerektirebilir.)</em></p>
<p><object id="obj1" width="405" height="445" classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" border="0">
<param name="movie" value="http://www.buraksenyurt.com/makale/images/Lease_1.swf" />
<param name="quality" value="High" /> <embed type="application/x-shockwave-flash" width="405" height="445" src="http://www.buraksenyurt.com/makale/images/Lease_1.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" name="obj1" /></object></p>
<p>Burada dikkat ederseniz, metodun 3ncü çağırılışından itibaren nesneye ait kiralama süresi hep 2 saniye olarak kalmıştır. Bunun sebebi, 2nci çağırıştan sonra gelen 3ncü metod çağırışının artık RenewOnCallTime süresi sınırlarına dahil olmasıdır. Bu nedenle referansa ait kiralama süresi sonraki çağırımlarda sürekli olarak 2 saniyeye set edilmiştir. Bu sayede istemci 6 metod çağırımınıda başarılı bir şekilde yapabilmiştir. Oysaki kiralama süreleri aslında çok hassas dengeler üzerinde çalışmaktadır. Yapılacak ufak hatalar istemcileri başına sorun açabilir. Bunu görmek için istemci tarafındaki bekleme süresini 4 saniyeye çıkartalım ve uygulamamızı yeniden test edelim.<em>(Aşağıdaki video görüntüsü flash formatında olup bilgisayarınıza flash player kurmanızı gerektirebilir.)</em></p>
<p><object id="obj2" width="405" height="445" classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" border="0">
<param name="movie" value="http://www.buraksenyurt.com/makale/images/Lease_2.swf" />
<param name="quality" value="High" /> <embed type="application/x-shockwave-flash" width="405" height="445" src="http://www.buraksenyurt.com/makale/images/Lease_2.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" name="obj2" /></object></p>
<p>Dikkat ederseniz, 3ncü metod çağırımında uygulama bir istisna ile sonlanmaktadır. İlk metod çağırımında kiralama süresi yaklaşık olarak 6 saniye civarındadır. İkinci çağırıma geçerken uygulama 4 saniye duraksamıştır. Bu nedenle kiralama süresi bu nesne örneğimiz için yaklaşık 2 saniyeye kadar inmiştir. 3ncü metod çağırımında önce istemci uygulama 4 saniye daha bekler. Oysa bu süre içerisinde, uzak nesne referansı kiralama ömrünü doldurduğundan, garbage collector tarafından toplanılmak üzere işartlenir. Dahası bu 4 saniyelik bekleme süresi içerisinde başka bir metod çağırımı olmadığından RenewOnCallTime süresinin sınırlarıda artık geçerli değildir.</p>
<p>Dolayısıyla istemci artık olmayan bir referansa çağrıda bulunmaya çalışmaktadır. Bunun doğal sonucu olarakta istemci uygulamada bir istisna oluşacaktır. Dolayısıyla çalışma zamanında bu gibi durumların oluşabileceğini düşünmek ve buna göre hareket etmekte fayda vardır. Dilerseniz, bir uzak nesne referansının mümkün olduğunca uzun süre yaşamasını isteyebilirsiniz. Buna genellikle sonsuz kiralama süresi <strong>(infinity lease time)</strong> denir. Bunun için tek yapmanız gereken uzak nesnede ezdiğimiz InitializeLifetimeService metodundan geriye null bir referans döndürmek olacaktır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public override object InitializeLifetimeService()
{
return null;
}</pre>
<p>Bu durumda az önce duraklama süresi 4 saniye olan istemci uygulamayı çalıştırdığımızda bir sorun ile karşılaşmadan tüm metod çağrıların sonuçlandırıldığını görürüz. <em>(Aşağıdaki video görüntüsü flash formatında olup bilgisayarınıza flash player kurmanızı gerektirebilir.)</em></p>
<p><object id="obj3" width="397" height="437" classid="clsid:D27CDB6E-AE6D-11CF-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" border="0">
<param name="movie" value="http://www.buraksenyurt.com/makale/images/Lease_3.swf" />
<param name="quality" value="High" /> <embed type="application/x-shockwave-flash" width="397" height="437" src="http://www.buraksenyurt.com/makale/images/Lease_3.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" name="obj3" /></object></p>
<p>Tabi burada istemci tarafında dikkat edilmesi gereken bir husus vardır. Buda Infinity Lease Time olması durumunda, istemci üzerinden o anki referansa ait CurrentLeaseTime süresinin okunamayacağıdır. Buda çalışma zamanında istisnaya neden olacak bir durumdur.</p>
<p>Bir uzak nesneye ait kiralama sürelerini sadece kod tarafında değil xml tabanlı konfigurasyon dosyalarında da tutabiliriz. Bildiğiniz gibi, Remoting uygulamalarının daha esnek olması açısından channel, port, type, objectUri gibi bir takım bilgileri konfigurasyon dosyalarında tutmaktayız. Dolayısıyla sunucu uygulamamız için gerekli konfigurasyon dosyasını aşağıdaki gibi oluşturabiliriz.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="4500" />
</channels>
<lifetime leaseTime="6" renewOnCallTime="2" leaseManagerPollTime = "1" />
<service>
<activated type="RemoteObjects.RemoteObj,RemoteObjects"/>
</service>
</application>
</system.runtime.remoting>
</configuration></pre>
<p>Kiralama sürelerine ait bilgiler eğer aksi belirtilmesse her zaman saniye cinsinden uzunlukları temsil eder. Ancak farklı takılar kullanarak bu süre cinslerini değiştirmemiz mümkündür. Bu değerleri aşağıdaki tabloda bulabilirsiniz.</p>
<table id="table46" style="border-collapse: collapse; width: 314px;" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td style="width: 81px;"><strong> Harf</strong></td>
<td style="width: 81px;"><strong> Anlamı</strong></td>
<td style="width: 81px;"><strong> Örnek</strong></td>
</tr>
<tr>
<td width="81">D</td>
<td width="63">Gün</td>
<td width="134">3D (3 gün)</td>
</tr>
<tr>
<td width="81">H</td>
<td width="63">Saat</td>
<td width="134">2H (2 saat)</td>
</tr>
<tr>
<td width="81">M</td>
<td width="63">Dakika</td>
<td width="134">45M (45 dakika)</td>
</tr>
<tr>
<td width="81">S</td>
<td width="63">Saniye</td>
<td width="134">15 (15 saniye)</td>
</tr>
<tr>
<td width="81">MS</td>
<td width="63">Milisaniye</td>
<td width="134">100 (100 milisaniye)</td>
</tr>
</tbody>
</table>
<p><br />Özetlemek gerekirse, bir uzak nesnenin varsayılan kiralama süresini (lease time) değiştirebilir ve referansların yaşam sürelerini etkilyebiliriz. Bu makalemizde bunu gerçekleştirmek için programatik olarak ve konfigurasyon bazında kullanabileceğimiz yolları inceledik. Bir sonraki makalemizde, Sponsor tekniğini incelemeye çalışacağız. Böylece geldik bir makalemizin daha sonuna bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/makale/images/LeaseManagement.rar">Örnek kod için tıklayınız.</a></p>2006-04-06T12:00:00+00:00.net remotinglease time managementbsenyurtRemoting mimarisi göz önüne alındığında dikkat çekici noktalardan bir tanesi, sunucu tarafında oluşturulan uzak nesnelerin (remote object) yaşam süreleridir. İstemciler, uzak nesnelere ait referansları kullanırken bunların yaşam sürelerini sunucu tarafındaki konfigurasyon belirler. Bu istemcilerin sunucu tarafındaki referanslara ait kaynaklara açıkça müdahale edememesinin de bir sonucu olarak görülebilir. Sunucu tarafında yapılan bu yaşam sürelerinin yönetimine kısaca Kiralık Süre Yönetimi (Lease Time Management) denmektedir. Bu makalemizde kısaca bu konuyu incelemeye çalışacağız.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=49f4aa42-145d-4735-acd1-2109b8208a860https://www.buraksenyurt.com/trackback.axd?id=49f4aa42-145d-4735-acd1-2109b8208a86https://www.buraksenyurt.com/post/-Net-Remoting-Lease-Time-(Kiralc4b1k-Sure)-Yonetimi-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=49f4aa42-145d-4735-acd1-2109b8208a86