سعيد احمدلوئي

همان‌گونه كه مي‌دانيد وب‌سرويس‌ها امكاني جهت دسترسي به اشياء و توابع از طريق شبكه را فراهم مي‌كنند (در اين زمينه مي‌توانيد به مقاله وب سرويس‌ها و XML در شماره 52 ماهنامه‌شبكه مراجعه نماييد.) وب سرويس‌ها سيستمي بسيار ساده دارند و از آن‌ها مي‌توان به عنوان ابزاري جهت برقراري ارتباط بين سيستم‌هاي با Platformهاي مختلف استفاده كرد، ولي با تمام قابليت‌ها و امكاناتي كه وب‌سرويس‌ها دارند اين تكنولوژي در برخي موارد به اندازه كافي انعطاف‌پذير و سريع نيست و لذا پاسخگوي گروه خاصي از نيازها نيست. بزرگترين عاملي كه اين محدوديت را ايجاد مي‌كند نياز وب سرويس‌ها به IIS و يا به عبارت ديگر ASP.NET runtime مي‌باشد. جهت فائق‌آمدن به اين مسايل مي‌توان از Dot NET Remoting استفاده كرد. در واقع Dot NET Remoting هم دقيقاً همان سرويسي را فراهم مي‌كند كه وب سرويس‌ها فراهم مي‌كنند ولي داراي ويژگي‌هاي خاصي مي‌باشد كه انعطاف و سرعت زيادي نسبت به وب سرويس‌هاي عادي فراهم مي‌كند.


مقدمه‌
به‌طور كلي اگر ساختار يك وب سرويس، (منظور از وب سرويس در اينجا NET ASP . وب‌سرويس مي‌باشد) را بررسي كنيم همواره دو جزء در ساختار آن وجود دارد: جزء اول همان كلاس‌هايي مي‌باشد كه درست مي‌كنيد. به عبارت ديگر در داخل اين كلاس‌ها منطق‌‌كاري وب‌سرويس و توابع عمومي و خصوصي وب سرويس قرار مي‌گيرند و پس از كامپايل، اين كلاس‌ها به يك dll تبديل مي‌شوند. جزء بعدي يك وب سرويس كه همواره موردنياز مي‌باشد برنامه‌اي است كه به يك پورت سيستم گوش مي‌دهد و درخواست‌هاي كلاينت‌ها را مي‌گيرد و به جزء اول مي‌دهد و پس از پردازش پاسخ را گرفته و به كلاينت ارسال مي‌كند. در توليد وب‌سرويس‌هاي عادي تقريباً تمام تمركز روي جزء‌ اول يعني كلاس‌هاي آن است. جزء بعدي همان IIS است كه كافي است در برخي موارد تنظيمات خاصي روي آن انجام دهيم. با استفاده از NET Remoting. سيستم‌هايي جهت دسترسي از طريق شبكه فراهم خواهيم كرد كه در واقع دو بخش يك وب سرويس در آن‌ها هم وجود دارد، ولي اين‌بار مي‌توانيم ازIIS استفاده نكنيم و خودمان برنامه ميزبان (منظور برنامه‌اي كه به شبكه گوش مي‌دهد و تبادل اطلاعاتي بين كلاينت‌ها و كلاس‌هاي ما را فراهم مي‌كند) را بنويسيم. با اين توصيف در واقع مي‌توان گفت كه ASP.NET Web Serviceها نوع ساده‌شده‌اي از سيستم‌هايي هستند كه توسط NET Remoting. مي‌توان توليد كرد چرا كه در استفاده از ASP.NETWeb Serviceها مجبور به استفاده از IIS به عنوان برنامه ميزبان هستيم.
قبل از اين‌كه شروع به پياده‌سازي يك نمونه كامل نماييم، با يك ديد كلي اجزاء سيستم‌ پياده‌سازي شده توسط NET Remoting را مورد بررسي قرار مي‌دهيم.


براي مشاهده تصوير در اندازه واقعي
روي آن كليك كنيد

كلاس‌ها
در سمت سرور، remote object همان كلاس‌هايي مي‌باشند كه منطق اصلي كاري را تشكيل مي‌دهند. اين كلاس‌ها به صورت يك dll روي سرور قرار مي‌گيرند و توابع public اين كلاس‌ها هستند كه در نهايت از طريق كلاينت‌‌ها فراخواني شده و مورد استفاده قرار مي‌گيرند. Formatter كلاسي است كه پاسخ‌هاي سرور (مقادير ارسالي از remote object) را كه به صورت يك سري اشياء مي‌باشند را گرفته و با كدبندي خاصي به يك سري از بايت‌ها تبديل مي‌كند كه مناسب جهت ارسال از طريق شبكه مي‌باشد. همچنين درخواست‌هايي را هم كه كلاينت ارسال مي‌كند از كدبندي خاص آن خارج كرده و تبديل به يك شيء مي‌كند كه قابل‌فهم براي remote object مي‌باشد. سمت كلاينت نيزformatter دقيقاً همين كار را انجام مي‌دهد ولي جهت عكس. به عمليات تبديل يك شيء به فرمتي قابل‌ارسال و يا نگهداري كه توسط Formatter انجام مي‌شود Serialize و به عكس اين عمل Deserialize مي‌گويند. Channel هاي سمت كلاينت و سرور پروتكل ارتباطي بين كلاينت و سرور و تنظيمات مربوط به آن را تعيين مي‌كنند. اين‌ها در واقع همان برنامه ميزبان هستند كه در سمت سرور در حالت Listening قرار دارد و در سمت كلاينت به صورت كلاينت مي‌باشند. اما كلاس Proxy كه فقط در سمت كلاينت وجود دارد كلاسي است كه دقيقاً مانند كلاس‌هاي داخل remote object مي‌باشد. كلاينت قادر به فراخواني توابع remote object به صورت مستقيم و بي‌واسطه نيست چرا كه remote object روي سيستم ديگري در شبكه قرار دارد و لذا كلاسي تحت عنوان كلي Proxy با همان توابع Public كه remote object  فراهم مي‌كند در سمت كلاينت ايجاد مي‌شود كه از ديد كلاينت همانند ساير كلاس‌هاي عادي مي‌باشد؛ ولي وقتي كلاينت تابعي از اين كلاس‌ را فراخواني مي‌كند اين تابع يك پيام جهت فراخواني تابع مشابه خود درremote object ايجاد كرده و ارسال مي‌كند و پس از دريافت پاسخ، نتيجه را در اختيار كلاينت قرار مي‌دهد.
توجه داشته باشيد كه تمام اين كلاس‌ها به طور كامل در اختيار شما مي‌باشند و شما مي‌توانيد هر تغيير منطقي موردنياز را در هر كدام از اين كلاس‌ها اعمال كنيد و اين همان انعطاف‌پذيري كاملي مي‌باشد كه NET Remoting . در اختيار شما قرار مي‌دهد. البته توليد تمام اين كلاس‌ها احتمالاً براي برخي زياد هم خوشايند نخواهد بود. چرا كه قطعاً زمان زيادي صرف توليد و اشكال‌زدايي آن‌ها مي‌شود. جهت رفع اين مشكل مي‌توانيد از NET. كمك بگيريد چرا كه اگر نيازي به قابليت‌هاي خاص در اين سا ختار نداريد.  دات‌نت تمام اين كلاس‌ها را با رفتار عادي آن‌ها براي شما توليد مي‌كند؛ مگر دو كلاس كه مي‌بايستي شما آن‌ها را توليد كنيد. همان‌طور كه حدس زديد يكي كلاس remote object  مي‌باشد كه رفتار اصلي سيستم شما و قابليت‌هايي كه مي‌خواهيد ارايه دهيد در اين كلاس قرار دارد و ديگري برنامه يا كلاس ميزبان مي‌باشد كه قسمت channel را فراهم مي‌كند.
در بيشتر موارد هدف استفاده از NET Remoting . بي‌نياز شدن از IIS يا ASP.NET Runtime مي‌باشد. در ادامه مثال كاملي كه در آن به جاي IIS از يك برنامه console استفاده مي‌شود را بررسي مي‌كنيم. به‌عبارت ديگر برنامه ميزبان يك console Application مي‌باشد. در مثال ارايه شده برنامه كلاينت و سرور به صورت console مي‌باشند تا ضمن حفظ سادگي، رفتار دقيق كلاينت و سرور قابل مشاهده باشد. بديهي است در صورت تمايل مي‌توانيد با انجام چند تغيير جزيي آن‌ها را به برنامه‌هاي windows form تبديل كنيد. در ادامه راهنمايي‌هايي هم جهت اين تبديل آورده شده است. (كدهاي آماده مثال را مي‌توانيد از سايت ماهنامه شبكه دانلود كنيد).

يك مثال
به مثال زير توجه كنيد. همان‌طور كه اشاره شد Remote Object كلاس يا كلاس‌هايي است كه منطق اصلي موردنظر سيستم در آن قرار دارد. در اين‌جا يك كتابخانه ساده (dll) يا يك تابع عمومي را به عنوان remote object  پياده‌سازي مي‌كنيم.
همان‌طور كه ملاحظه مي‌كنيد از توابع console استفاده شده تا پيام‌هاي مناسبي هنگام فراخواني سازنده كلاس و يا تابع Hello در خروجي command Prompt چاپ شود. براي توليد اين remote object مي‌توانيد يك پروژه از نوع classlibrary درNET. ايجاد كرده و كد مربوط را در كلاسي كه به صورت پيش‌فرضNET . در پروژه ايجاد مي‌كند بنويسيد و يا مي‌توانيد كد را در يك فايل متني ساده تايپ كنيد و با پسوند.cs  ذخيره كنيد و با استفاده از دستور زير آن را كامپايل كنيد: .Csc/t:library/out:My Remote object
dll My Remote object.cs 
   توجه داشته باشيد كه remote object از اين كلاس ارث‌بري كند (كلاس Marshal By Refobject  قابليت‌هاي خاصي به كلاسي كه از او ارث‌بري كند مي‌دهد تا آن كلاس جهت ارايه سرويس‌هاي ماندگار در حافظه (lifetime) بهينه شود).

using System;
using System.Runtime.Remoting;


namespace Client
{
	class Client
	{
		static void Main(string[] args)
		{
		   RemotingConfiguration.Configure("Client.exe.config");
		   MyRemoteObject.MyRemoteObject obj=new 
                             MyRemoteObject.MyRemoteObject();    Console.WriteLine(obj.Hello());    Console.ReadLine(); } } }


Remote Server

قسمت بعدي پياده‌سازي remote server و به عبارت ديگر، برنامه ميزبان مي‌باشد، برنامه ميزبان و remote object را مي‌توانيد در يك فايل يا اسمبلي پياده‌سازي كنيد، ولي استفاده از دو فايل متفاوت قابليت استفاده مجدد
(reuse ability) سيستم را بالا مي‌برد.
وظيفه برنامه ميزبان، درست كردن يك كانال ارتباطي و گوش دادن به يك پورت سيستم مي‌باشد تا به اين وسيله درخواست‌هاي كلاينت‌ها را گرفته و به remote object بدهد. كانال ارتباطي remote server يا برنامه ميزبان را مي‌توان با استفاده از فايل پيكربندي و يا با استفاده از برنامه‌نويسي تنظيم نمود كه هر كدام معايب و مزاياي خاصي دارد. وقتي كه از فايل پيكربندي (configuration file) استفاده مي‌شود، كدنويسي لازم در برنامه ميزبان به حداقل مي‌رسد و همچنين جهت تعويض تنظيمات كانال (به عنوان مثال شماره پورت، يا پروتكل و يا ...) نيازي به دستكاري كدبرنامه و كامپايل مجدد آن نداريد، بلكه فقط كافي‌است تنظيمات موردنظر را در فايل پيكربندي انجام دهيد. فايل پيكربندي فايلي است با فرمت XML كه اطلاعات كانال را در آن قرار مي‌دهند. برنامه ميزبان هنگام اجرا، اطلاعات فايل پيكربندي را خوانده و با توجه به تنظيماتي كه در آن ثبت شده، كانال ارتباطي را ايجاد مي‌كند، البته در صورتي كه از فايل پيكربندي استفاده نكنيد نيز مزيت خاصي خواهيد داشت و آن تغيير دادن تنظيمات كانال در زمان اجرا توسط برنامه مي‌باشد. در اين‌جا جهت توليد برنامه ميزبان از فايل پيكربندي استفاده خواهيم كرد.
اسم فايل پيكربندي را همنام با فايل اجرايي برنامه ميزبان بگذاريد با پسوند config. در اين صورت نام فايل Simpleserver.config خواهد شد. كدهاي داخل اين فايل به صورت زير مي‌باشند.

<configuration>
     <system.runtime.remoting>
         <application name="Client">
              <client url="tcp://localhost:9000/Server">
                  <wellknown
                  type="MyRemoteObject.MyRemoteObject, MyRemoteObject"
                  url="tcp://localhost:9000/MyRemoteObject"/>
              </client>
              <channels>
                  <channel ref="tcp client" />
              </channels>
          </application>
      </system.runtime.remoting>
</configuration>


همان‌طور كه ملاحظه مي‌كنيد اطلاعات كانال و remote object در داخل عنصرsystem.runtime.remoting  قرار دارد. عنصر application در فيلد name ، نام سرور را مشخص مي‌كند و در داخل عنصر service  مشخصات remote object قرار دارد دو فيلد wellknown و mode مربوط به دسته‌بندي remote objectها مي‌باشد كه در ادامه دسته‌بندي و انواع مختلف remote objectها را توضيح خواهم داد. فعلاً  اين دو فيلد را همين‌گونه بپذيريد. در فيلد type مشخص مي‌شود كه اين سرويس مربوط به كدام remote object مي‌باشد. در اين فيلد به زيرساخت NET Remoting. گفته مي‌شود كه در كدام اسمبلي و در چه كلاس و namespaceاي در آن اسمبلي remote object قرار دارد. اگر به فايل توجه كنيد، مقدار رشته‌اي فيلد type با كاما (,) دو قسمت شده است قسمت اول namespace و كلاس مربوط به remote object را مشخص مي‌كند و قسمت دوم نام اسمبلي مربوط به remote object را.
(درNET. كدهاي نوشته شده در بسته‌هاي خاصي به نام assembly بسته‌بندي مي‌شوند. هر اسمبلي دستوراتي به زبان IL و يك سري metadata دارد كه NET runtime. با استفاده از اين اطلاعات آن را اجرا مي‌كند. توجه داشته باشيد كه يك اسمبلي مي‌تواند در چند فايل باشد و يا برعكس چند اسمبلي در يك فايل. در اينجا اسمبلي remote object ما در در داخل يك فايل همنام با اسمبلي آن قرار دارد.) در فيلد Object Url آدرسي را مشخص مي‌كنيم كه قرار است كلاينت‌ها جهت دسترسي به remote object اين آدرس را بدهند. بعداً در فايل پيكربندي برنامه كلاينت خواهيد ديد كه فيلدي با نام Url وجود دارد كه آدرس remote object را در آن خواهيم نوشت. در اين آدرس پس از مشخص كردن پروتكل و IP آدرس كامپيوتري كه برنامه ميزبان در آن قرار  دارد، مقداري كه به فيلد Object Url داده‌ايم را در آن قرار خواهيم داد. فيلد Object Url مي‌تواند يك URL كامل باشد بدين صورت كه remote object در روي سيستم ديگري در وب قرار دارد و يا حتي remote object خود يك وب سرويس مي‌باشد. در اينجا به اين فيلد فقط نام اسمبلي remote object را مي‌دهيم و كلاينت هم در فايل پيكربندي خود در فيلد Url از همين نام استفاده خواهد كرد.
اگر دقت كرده باشيد، متوجه شده‌ايد كه مشخصات remote object در داخل عنصر قرار گرفته است. در واقع جالب است بدانيد كه در داخل عنصر<>service به هر تعداد remote object و يا به عبارت ديگر سرويس كه بخواهيم مي‌توانيم معرفي كنيم؛ به شرط اين‌كه به هر كدام از آن‌ها كانال خاصي اختصاص دهيم و به‌طور كلي از عهده مديريت چنين سيستمي برآييم. در چنين حالتي يك برنامه ميزبان درخواست‌هاي استفاده از چندين remote object را گرفته و handel مي‌كند.
عنصر channels تنظيمات مربوط به كانال يا كانال‌هاي ارتباطي را در خود دارد. در اينجا فقط از يك كانال استفاده خواهيم كرد و به جاي ايجاد كانال جديد، از كانال‌هاي تعريف‌شده در Machine.config استفاده مي‌كنيم. جهت اين‌كار از فيلد channel ref و سپس ازid كانال تعريف شده در machine.config استفاده مي‌كنيم. فيلد port هم شماره پورتي كه برنامه ميزبان به آن گوش خواهد داد را مشخص مي‌كند. فايل machine.config فايل XMLاي است كه تنظيمات ويژه‌اي در سطح سيستم در آن قرار دارد، از جمله كانال‌هايي كه به صورت پيش‌فرض در آن تعريف شده‌اند اين فايل در مسير Microsoft.NET Frameuork CONFIG درSystem Root  قرار دارد.
 با ديدن قسمتي كه در آن كانال tcp client تعريف شده است، متوجه مي‌شويد كه تعريف كانال جديد در فايل پيكربندي برنامه ميزبان كار چندان دشواري نيست. ضمناً علاوه براين كانال پنج كانال ديگر نيز در اين فايل تعريف شده‌اند كه از كانال tcp client در پياده‌سازي برنامه كلاينت استفاده خواهيم كرد. با وجود فايل پيكربندي، تمام كاري كه برنامه ميزبان بايد انجام دهد، خواندن محتويات فايل پيكربندي و ايجاد كانال و قرار دادن آن در حالت listining جهت دريافت درخواست‌هاي كلاينت‌ها مي‌باشد. براي انجام تمام اين كارها كافي‌است يك تابع static كه در كلاس Remoting Configuration قرار دارد را فراخواني كنيم و نام فايل پيكربندي را به عنوان آرگومان به آن بدهيم.
برنامه ميزبان را به هر صورتي كه بخواهيد مي‌توانيد پياده‌سازي كنيد. در اينجا برنامه Console پياده‌سازي مي‌كنيم. در صورت تمايل مي‌توانيد يك برنامه windows Form ساده بنويسيد كه همين كار را انجام دهد. نكته‌اي كه در هر حال بايد به خاطر داشته باشيد اين  است كه تا وقتي برنامه ميزبان در حال اجراست و به كانال گوش مي‌دهد، كلاينت‌ها مي‌توانند از remote object استفاده كنند و به محض اين‌كه برنامه ميزبان از حالت اجرا خارج شود، امكان دسترسي به remote object توسط كلاينت‌ها وجود نخواهد داشت. اين موضوع موجب مي‌شود كه انتخاب برنامه ميزبان از نوع برنامه‌هاي سرويس (windows service) كه هميشه در حال اجرا هستند، مناسب باشد. با اين وجود در اين‌جا براي سادگي از يك برنامه console استفاده خواهيم كرد كه تا زماني كه كاربر كليد Enter را نزند، برنامه در حالت اجرا باقي خواهد ماند و خواست ما تأمين مي‌شود. كد برنامه ميزبان به دو صورت زير مي‌باشد:

//MyRemoteObject.cs

using System;
namespace MyRemoteObject
{
	public class MyRemoteObject : System.MarshalByRefObject
	{
		public MyRemoteObject()
		{
			Console.WriteLine("Constructor called");
		}
		
		public string Hello()
		{
			Console.WriteLine("Hello called");
			return "Hello, .NET Client!";
		}
	}
}


همان‌طور كه ملاحظه مي‌كنيد، اين برنامه فقط شامل يك فراخواني ساده تابع configure مي‌باشد كه نام فايل پيكربندي به عنوان آرگومان به آن داده شده است. تابع ()Readline تا زماني كه كاربر كليد Enter را نزده است، منتظر مي‌ماند. از اين رو برنامه هم در حال اجرا باقي خواهد ماند. پس از كامپايل و درست كردن فايل exe برنامه ميزبان توجه داشته باشيد كه لازم است فايل پيكربندي و dll. مربوط به remote object را كه قبلاً ساخته بوديد، به مسيري كه برنامه ميزبان در آن قرار دارد كپي كنيد.

Client Program
برنامه كلاينت قرار است از remote object توليد شده در قسمت قبل استفاده كند. اين برنامه هم مانند سرور از يك فايل پيكربندي و يك فايل exe. تشكيل شده است. نام فايل پيكربندي برنامه كلاينت را هم به صورت قبل با اضافه كردن config. به نام فايل exe آن بسازيد. اين فايل url مربوط به remote object پروتكل و شماره پورت و نام سيستمي را كه remote object روي آن قرار دارد مشخص مي‌كند. اين فايل به صورت زير مي‌باشد:

//SimpleServer.cs

using System;
using System.Runtime.Remoting;

namespace Server
{
	class SimpleServer
	{
            static void Main(string[] args)
	      {
		RemotingConfiguration.Configure("SimpleServer.exe.config");
		Console.WriteLine("Press return to exit");
		Console.ReadLine();
	      }
	}
}

 

اطلاعات موجود در اين فايل مشخص هستند. فقط در مورد channel توجه كنيد كه اين‌بار از tcp client تعريف شده در machine config استفاده شده است. همانند برنامه سرور در كلاينت هم با استفاده از تابع configure فايل پيكربندي خوانده شده و تنظيمات لازم انجام مي‌گيرد و در خط بعد يك object از كلاس remote object تعريف شده و تابع ()Hello آن فراخواني مي‌شود. براي توليد برنامه كلاينت هم مانند قبل مي‌توانيد از .NET استفاده كرده و در صورت تمايل يك برنامه windows form  بنويسيد و يا در يك فايل متني ساده كد لازم را بنويسيد و از كامپايلر#C  براي توليد exe. آن استفاده كنيد. توجه داشته باشيد كه برنامه كلاينت لازم استreference اي به remote object داشته باشد. براي اين‌كار اگر از NET. استفاده مي‌كنيد، با كليك راست درsolution explorer و انتخاب Add reference ، مي‌توانيد reference را اضافه كنيد و اگر از كامپايل خط فرمان #C استفاده مي‌كنيد، دستور كامپايل فايل به صورت زير خواهد بود:
Csc/target:exe/reference My RemoteObjcet.dll
 Simple Client.cs 
سؤال مهمي كه در اين‌جا پيش مي‌آيد اين است كه آيا چنانچه بعد از نصب سيستم (كلاينت‌ها و سرور و remote) object بخواهيم تغيير خاصي در منطق كاري remote object (و نه در رابط كاربري آن يعني توابع عمومي كه توسط كلاينت‌ها استفاده مي‌شوند) بدهيم، آيا لازم است نسخه جديد remote object را به تمام سيستم‌هايي كه برنامه كلاينت در آن نصب شده انتقال دهيم؟ بديهي است كه اين‌كار لازم نيست؛ چرا كه اگر اين‌گونه باشد، استفاده از
NET remoting. معني و مفهوم خود را از دست مي‌دهد. لازم است در هنگام توليد برنامه كلاينت referenceاي به remote object در آن ايجاد كنيد و برنامه كلاينت را بنويسيد. هنگام نصب برنامه كلاينت، remote object  هم با آن روي سيستم نصب خواهد شد، ولي در ادامه چنانچه نياز به ارتقاء remote object داشته باشيد، كافي ‌است remote object جديد را روي سرور نصب كنيد. كلاينت‌ها به صورت اتوماتيك از remote object جديد استفاده خواهند كرد كد برنامه كلاينت به صورت زير مي‌باشد:

<configuration>
      <system.runtime.remoting>
          <application name="SimpleServer">
             <service>
                  <wellknown
                  mode="SingleCall"
                  type="MyRemoteObject.MyRemoteObject, MyRemoteObject"
                  objectUri="MyRemoteObject"/>
             </service>
             <channels>
                  <channel ref="tcp server" port="9000" />
             </channels>
          </application>
      </system.runtime.remoting>
</configuration>


پس از ساختن فايل exe. برنامه كلاينت سيستم آماده تست مي‌باشد. براي تست ابتدا برنامه سرور را اجرا كنيد تا كانال سمت سرور را ساخته و در حالت listening قرار دهد. سپس كلاينت را اجرا كنيد. اگر همه چيز تا اينجا درست باشد، سيستم كلاينت مقدار بازگشتي از تابع Hello مربوط به remote object را چاپ خواهد كرد. ضمناً در سمت سرور نيز فراخواني انجام شده و تابع Hello در پنجره مربوط به سرور اعلان خواهد شد.
در اين‌جا ليست كامل فايل‌هايي را كه براي اين سيستم درست كرديم مي‌توانيد ببينيد. 

توضيحات

Assembly

Source file 

Class

كلاس مربوط به Remote object كه تابع Hello () در آن مي‌باشد.

My Remote
Object.dll 

  My Remote Object.cs

My Remote object

برنامه ميزبان كه كانال ارتباطي سرور را با استفاده از اطلاعات موجود در فايل پيكربندي ايجاد مي‌كند.

 Simple
Server.exe

 Simple Server.cs

Simple Server

برنامه كلاينت كه از سرويس استفاده مي‌كند. اين برنامه اطلاعات لازم را از فايل پيكربندي client.exe.confing  گرفته و به سرور وصل مي‌شود.

Simple Chient.exe

Simple Chient.cs

SimpleChient

 همان‌طور كه قبلاً اشاره شد، remote objectها داراي دسته‌بندي خاصي مي‌باشند كه در اين قسمت به صورت مختصر آن‌ها را توضيح مي‌دهيم. به ‌طور كلي remote objectها به دو دسته كلي well-known و client-activated تقسيم مي‌شوند. نوع well-known خود در دو حالت مي‌تواند مورد استفاده قرار گيرد:
Singleton و.SingleCall (مثالي كه توضيح داده شد، از نوع well-known و دسته singlecall بود.) نوع well-known همان‌طور كه از نامش هم پيداست، اشيايي شناخته شده هستند كه با Url شان آدرس‌دهي مي‌شوند remote objectهاي وwellknown (Single Singleton) Call  و به صورت Stateless هستند؛ يعني هربار كه كلاينت تابعي از remote object را فراخواني مي‌كند، هيچ‌گونه سابقه‌اي از اين فراخواني نگهداري نمي‌شود و در فراخواني بعدي نمي‌توانيد هيچ‌گونه استنادي به فراخواني‌هاي قبلي بكنيد. تفاوت Singleton و Single Call نيز در اين است كه در حالت Single Call شي remote object در فراخواني هر تابع ساخته مي‌شود و پس از فراخواني از بين مي‌رود تا فراخواني تابع بعدي، ولي در حالت Singleton فقط يك Object ايجاد مي‌شود و تمام فراخواني‌ها از طريق آن object صورت مي‌پذيرند. لذا مي‌توان از اين حالت جهت اطلاع‌رساني عمومي به تمام كلاينت‌ها استفاده كرد. جهت درك نوع singleton ، مي‌توانيد نوع Singleton را مانند متدها يا propertyهاي static در كلاس تصور كنيد كه بين تمام اشياي آن كلاس به اشتراك گذاشته مي‌شوند. البته اين مطلب فقط جهت درك singleton مي‌باشد و هيچ‌گونه ارتباطي بين اين دو مقوله وجود ندارد. تفاوت عمده remote objectهاي clientactivated عمده با نوع قبلي در اين است كه به صورت statefull هستند و مي‌توانيد به سابقه فراخواني‌هاي قبلي استناد كنيد. البته در استفاده از آن‌ها هميشه به خاطر داشته باشيد كه مقداردهي به يك property ، نيازمند يك ارتباط شبكه‌اي با remote object مي‌باشد. لذا جهت دستيابي به كارايي قابل قبول، سعي كنيد هميشه با حداقل فراخواني‌هاي متدها وproperty هاي remote object  به هدف خود برسيد. اشيا Client activated توسط Url  شناسايي نمي‌شوند، بلكه NET Runtime. هنگام درخواست كلاينت باتوجه به نوع كلاس درخواستي شي‌ موردنظر را تشخيص داده و يك instance از آن مي‌سازد.
تعيين نوع remote object و مد آن در فايل پيكربندي انجام مي‌شود و كليت كاركرد و سيستم NET Remoting.  براي تمام اين انواع به همان صورت مي‌باشد كه توضيح داده شد. لذا در مورد انواع مختلف remote objcetها نگران نباشيد. بديهي است سيستم NET Remoting. بسيار فراتر از آن است كه در يك مقاله به تشريح تمام جوانب آن پرداخت. با اين وجود در اين مقاله تا حد امكان مفاهيم به صورت ساده ارايه شدند و اكنون مي‌توانيد سرويس‌هاي ساده مبتني بر NET Remoting. را پياده‌سازي كنيد.

 

منابع:
         1-MSDN  
         2- Wrox Press) C Web Service)