بخشی از مقاله
مفهوم سوكت و پورت و آدرس
اصلي ترين عامل در يك ارتباط شبكه سوكت ( soket ) ناميده مي شود . سوكت در دانشگاه بركلي ، كاليفرنيا ، و براي سيستم عامل يونيكس اختراع شد . سوكت اختراع شد تا ارتباطات شبكه را به عمليات خواندن / نوشتن فايل نزديك كند . با آن كه سوكت از آن موقع تاكنون پيشرفت هايي كرده ولي اساس آن ثابت مانده است .
در عصر ويندوز X/3 ، كه هنوز كاركردهاي شبكه جزء ذاتي سيستم عامل نشده بود ، شركت هاي زيادي پروتكل هاي لازم براي ارتباطات شبكه را عرضه مي كردند ، كه تفاوتهايي با يكديگر داشتند . در نتيجه هر شركت بايد مجموعه اي كامل از نرم افزارهاي شبكه را ارائه مي كرد . اين وضع خوشايند اكثر برنامه نويسان نبود . بنابراين تمام شركتهايي كه اين زمينه كار مي كردند ( از جمله ميكروسافت ) تصميم گرفتند يك مجموعه اي توابع برنامه نويسي ( API ) براي سوكت هاي ويندوز ( Winsock ) داشته باشند . بدين ترتيب تمام برنامه نويسان مي توانستند از يك سري توابع سازگار براي انجام ارتباطات شبكه استفاده كنند .
براي كار با فايل به يك شيء Cfile نياز داريم . پيام هاي شبكه هم وضع مشابهي دارند چون براي خواندن / نوشتن آنها به يك سوكت نياز هست ، با اين تفاوت كه باز كردن يك سوكت نياز به اطلاعات متفاوتي دارد . براي باز كردن يك فايل بايد نام و مسير آن را بدانيم . براي باز كردن يك سوكت بايد نام كامپيوتري كه گوش بزنگ است و پورتي ( Port ) كه به آن گوش مي دهد را بدانيم . در واقع نام كامپيوتر معادل شماره تلفن و پورت معادل شمارة داخلي مورد نظر است . پورت ها براي تغيير مسير ارتباطات شبكه هستند . به شكل زير نگاه كنيد .
شكل : پورت ارتباط شبكه را به مسير درست هدايت مي كند .
براي ارتباط با يك برنامه ديگر شبكه بايد پورت آن را هم بدانيد . اگر آدرس كامپيوتر و پورت را اشتباه كنيد ممكنست به برنامة ديگري وصل شويد ، يا اينكه اصلاً به جايي وصل نشويد ( درست مثل گرفتن يك شماره تلفن عوضي ) .
مبناي تمام برنامه هاي كاربردي لايه چهارم مفهومي بنام سوكت است كه اين مفهوم براي برقراري برنامه هاي تحت شبكه و تبادل جريان داده بين پروسه ها مي باشد برنامه با تعريف سوكت عملاً تمايل خود را براي تبادل داده ها به سيستم عامل اعلام مي كند ، و بدون درگير شدن با جزئيات پروتكل از سيستم عامل مي خواهد تا فضا و منابع مورد نياز را جهت برقراري يك ارتباط ايجاد كند . پروتكل IP در لايه زيرين TCP لايه وظيفه مسير يابي بسته ها را عهده دار است .
انواع سوكت و مفاهيم آنها
اگر بخواهيم از نظر اهميت انواع سوكت را معرفي كنيم دو نوع سوكت بيشتر وجود ندارد . ( انواع ديگري هم هستند ولي كم اهميت ترند ) . اين دو نوع سوكت عبارتند از :
. سوكتهاي نوع استريم كه سوكتهاي اتصال گرا ناميده مي شود .
. سوكتهاي نوع ديتاگرام كه سوكتهاي بدون اتصال ناميده مي شود .
اگر عادت به پيش داوري داريد براي تمايز بين مفهوم اين دو نوع سوكت . تفاوت
بين مفاهيم ارتباط نوع TCP و UDP را مدنظر قرار بدهيد . روش ارسال براي سوكتهاي نوع استريم همان روش TCP است و بنابراين داده ها با رعايت ترتيب و مطمئن با نظارت كافي بر خطاهاي احتمالي مبادله مي شوند . سوكتها نوع ديتاگرام نامطمئن است و هيچگونه تضميني در ترتيب جريان داده ها وجود ندارد .
اكثر خدمات و پروتكلهائي كه در لايه چهارم تعريف شده اند نيازمند حفظ اعتبار و صحت داده ها و همچنين رعايت ترتيب جريان داده ها هستند . بعنوان مثال پروتكل انتقال فايل ( FTP ) ، پروتكل انتقال صفحات ابرمتن ( HTTP ) يا پروتكل انتقال نامه هاي الكترونيكي ( SMTP ) ه
مگي نيازمند برقراري يك ارتباط مطمئن هتند و طبعاً از سوكتهاي نوع استريم بهره مي برند .
همانگونه كه قبلاً در مورد پروتكل TCP آموختيم پروتكلي است كه داده ها را با رعايت ترتيب و خالي از خطا مبادله مي نمايد و پروتكل IP كه در لايه زيرين آن واقع است با مسير يابي بسته ها روي شبكه سروكار دارد . سوكتهاي نوع استريم دقيقاً مبتني بر پروتكل TCP بوده و طبيعتاً قبل از مبادله داده ها بايد يك اتصال به روش دست تكاني سه مرحله اي برقرار بشود .
سوكتهاي نوع ديتاگرام مبتني بر پروتكل UDP است و بدون نياز به برقراري هيچ ارتباط و يا اتصال ، داده ها مبادله مي شوند و بنابراين تضميني بر رسيدن داده ها ، صحت داده ها و تضمين ترتيب داده ها وجود ندارد ولي باتمام اين مشكلات باز هم در برخي از كاربردها مثل انتقال صدا و تصوير يا سيستم DNS كه قبلاً آنرا بررسي كرديم مورد استفاده قرار مي گيرد . تنها حسن اين روش سرعت انتقال داده ها مي باشد .
در حقيقت شما با استفاده از سوكتها مي خواهيد يك ابزار براي استفاده از پروتكلهاي TCP يا UDP در اختيار داشته باشيد .
ارسال و دريافت به روش UDP با سوكتهاي ديتاگرام
توابع ارسال ، دريافت و پذيرش براي سوكتهاي نوع استريم كاربرد دارد . حال بايد ديد كه به چه صورت مي توان ارسال و دريافت را به روش UDP روي سوكتهاي نوع ديتاگرام انجام داد .
. برنامه سمت سرويس دهنده
الف ) يك سوكت از نوع ديتاگرام ايجاد كنيد . اين كار با فراخواني تابع socket() با پارامتر
SOCK – DGRAM انجام مي شود .
ب ) به سوكت ايجاد شده آدرس پورت موردنظرتان را نسبت بدهيد . ( با تابع bind() ) .
ج ) بدون هيچ كار اضافي مي توانيد منتظر دريافت داده ها بشويد . ( تا موقعي كه داده اي دريافت نشود ارسال معني نمي دهد . ) وقتي داده اي دريافت و پردازش شد آدرس برنامه مبدا ( آدرس IP و پورت ) مشخص شده و ارسال امكان پذير خواهد بود .
ارسال و دريافت وي سوكتهاي نوع ديتاگرام بوسيله توابع recvform() و sendto() انجام مي شود .
د ) نهايتاً سوكت ايجاد شده را ببنديد .
. برنامه سمت مشتري
الف ) يك سوكت از نوع ديتاگرام ايجاد كنيد . ( با تابعsocket() و پارامتر SOCK-DGRAM ) .
ب ) هرگاه نياز شد بدون هيچ كار اضافي داده هايتان را به سمت سرويس دهنده ارسال نماييد . تا وقتي كه به سمت سرويس دهنده ارسال نداشته باشيد ، دريافت داده ها معنا نمي دهد چرا كه شما براي سرويس دهنده شناخته شده نيستيد مگر اينكه داده اي را ارسال نمائيد . ارسال و دريافت را تا زماني كه نياز است انجام بدهيد .
ج ) سوكت ايجاد شده را ببنديد .
فرم كلي تابع ارسال داده مبتني بر سوكتهاي ديتاگرام بصورت زير است :
int sendto ( int sockfd , const void * msg , int len , unsigned int flags , const struct sockaddr * to , int tolen ) ;
. sockfd : مشخصه سوكت ديتاگرام كه با تابع socket() بوجود آمده است .
. msg : آدرس محل قرار گرفتن پيام در حافظه كه داده هاي ارسالي بايستي از آنجا استخراج شده و درون يك بسته UDP و درون يك بسته UDP قرار گرفته و ارسال شود .
. len : طول پيام ارسالي بر حسب بايت .
. to : استراكچري از نوع sockaddr كه قبلاً ساختار آنرا مشخص كرديم . در اين استراكچر بايد آدرس IP مربوط به ماشين مقصد و همچنين شماره پورت سرويس دهنده تنظيم شود.
. tolen : طول استراكچر sockaddr است كه به سادگي مي توانيد آنرا به مقدار ) sizeof struct sockaddr تنظيم نماييد .مقدار برگشتي اين تابع همانند تابع send() تعداد بايتي اسست كه سيستم عامل موفق به ارسال آن شده است . دقت كنيد كه اگر مقدار برگشتي ( 1-) باشد خطائي بروز كرده كه مي توانيد شماره خطا را در متغير سراسري error بررسي نمائيد . باز هم تكرار مي كنيم دليلي ندارد تعداد بايتي كه تقاضا ارسال آنها را داده ايد با تعداد بايتي كه ارس
ال شده يكي باشد . بنابراين حتماً مورد را در برنامه خود بررسي كرده و همچنين تقاضاي ارسال در هر مرحله را نزديك يك كيلو بايت درنظر بگيريد .
فرم كلي دريافت داده مبتني بر سوكتهاي ديتاگرام بصورت زير است :
int recvfrom ( int sockfd , void * buf , int len , unsingned int flags , struct sockaddr * from , int * fromlen ) ;
. sockfd : مشخصه سوكت ديتاگرام كه با تابع socket () بوجود آمده است .
. buf : آدرس محلي از حافظه كه سيستم عامل داده هاي دريافتي را در آن محل قرار خواهند داد .
. len : طول پيام كه بايد دريافت شود ( برحسب بايت ) .
. from : استراكچري است از نوع sockaddr كه سيستم عامل آنرا با مشخصات آدرس IP و آدرس پورت برنامه مبدأ تنظيم و به برنامه شما بر مي گرداند .
. len : طول استراكچري است كه سيستم عامل آنرا برگردانده است .
مقدار برگشتي اين تابع نيز تعداد بايتي است كه دريافت شده است . اين پارامتر براي پردازش
داده هاي دريافتي اهميت حياتي دارد .
ايجاد يك سوكت
اضافه كردن قابليت هاي شبكه به برنامه هاي Visual C++ با استفاده از كلاس هاي MFC Winsock نسبتاً ساده است و كلاس مبنا ، CasyncSocket ، يك ارتباط سوكت كاملو رويداد
گرا ( event – driven ) ارايه مي كند . كلاس هايي كه از اين كلاس مشتق مي شوند مي توانند رويداده را به دام انداخته و نسبت به آنها عكس العمل نشان دهند .
اولين كاري كه براي ساختن يك سوكت در برنامه بايد انجام دهيد تعريف يك متغير از نوع CasyncSocket در كلاس اصلي برنامه است :
class CMYDlg : public Cdialog
{
.
.
.
private :
Casyncsocket m- sMysocket ;
} ;
بستن كانال ارتباطي
بعد از آنكه برنامه كارش را به پايان رساند ، بايد كانال ارتباطي را با متد close ببندد . اين متد هيچ آرگوماني نمي گيرد :
m- sMysocket. Close ( ) ;
رويدادهاي سوكت
يكي از دلايل اصلي مشتق كردن از كلاس CasyncSocket امكان نوشتن تابع براي رويدادهاي سوكت است . كلاس CasyncSocket براي هر رويداد تابعي را فراخواني مي كند . اين توابع فقط در نام اختلاف دارند . تمام اين توابع به صورت protected تعريف شده اند و احتمالاً شما هم بايد توابع خود را چنين تعريف كنيد . تمام اين توابع يك پارامتر از نوع int مي گيرند كه آن را چك مي كنند تا مطمئن شوند خطايي روي نداده است . جدول زير توابع رويدادهاي كلاس سوكت را نشان مي دهد .
تابع مفهوم
OnAccept اين تابع ( در سوكت گوش دهنده ) مي گويد كه يك ارتباط در انتظار پذيرفته شدن بسر مي برد.
OnClose اين تابع مي گويد كه طرف مقابل سوكت خود رابسته است ، پاسخ اين رويداد معمولاً بستن سوكت خودي است .
OnConnect اين تابع مي گويد كه كانال ارتباطي با طرف مقابل يرقرار شده و اينك مي توان پيام رد وبدل كرد .
ONReceive اين تابع مي گويد كه مقداري داده از سوكت مقابل رسيده و آماده دريافت است .
OnSend اين تابع مي گويد كه سوكت آماده ارسال داده است . اين تابع بلافاصله بعد از برقراري ارتباط فراخواني خواهد شد . هر بار كه برنامة اجرا كنندة متد s end بخواهد داده بيشتري ارسال كند ، باز هم اين تابع فراخواني مي شود ؛ يعني ارسال بافر پايان يافته و برنامه مي تواند ادامه پيام را ارسال كند .
قبل از آنكه وارد مقوله برنامه نويسي سوكت بشويم بد نيست الگوريتم كل كاري كه بايستي در سمت سرويس دهنده و همچنين در سمت مشتري انجام بشود ، بررسي نمائيم :