سوکت ها و API در شبکه

سوکت ها و API در شبکه – آموزش شبکه درس 16

سوکت ها در شبکه به عنوان یک رابط برای ارسال و دریافت پیام به کار گرفته می شوند. در اینجا ما به بررسی سوکت ها پرداختیم و چند دستور در زبان C++  را ارائه دادیم که مکانیزم ارسال و دریافت پیام از طریق سوکت را تعریف می کند. البته تمامی این موارد را در پست های بعدی با دقت بیشتری برای شما توضیح خواهیم داد.

API چیست؟

مکانی که شروع به پیاده‌سازی یک نرم‌افزار تحت شبکه می‌کنیم، در واقع رابط کاربری خروجی شبکه به حساب می‌آید. به خاطر آن که بیشتر پروتکل‌هایی که در شبکه به کار گرفته می‌شوند به صورت نرم‌افزاری هستند (به ویژه آن‌هایی که در رتبه‌های بالاتر پشته پروتکل‌ها قرار دارند)، و به خاطر آن که تمام سیستم‌های کامپیوتری پروتکل‌های خودشان را به عنوان بخشی از سیستم عاملشان پیاده‌سازی کرده اند، در زمانی که ما به یک رابط کاربری «که به وسیله شبکه صادر شده است» اشاره می‌کنیم، ما به صورت معمول اشاره به رابطی داریم که سیستم عامل دستگاه مورد نظر برای ارتباط با زیرسیستم‌های مجموعه فراهم آورده است. این رابط کاربری در اغلب اوقات به عنوان رابط کاربری برنامه‌نویسی اپلیکیشن (API) شناخته می‌شود.

اگرچه، هر کدام از سیستم عامل به صورت رایگان API مناسب برای شبکه را معرفی می‌کند (و بیشتر آن‌ها نیز این چنین رابط‌هایی دارند)، در طول زمان برخی از این API‌ها به شدت مورد حمایت قرار گرفته اند؛ که به همین خاطر، آن‌ها به صورت پورت شد بر روی سیستم‌های عامل وجود دارند و به عنوان بخشی از سیستم‌ها شناخته می‌شوند. این که چه اتفاقی توسط رابط کاربری سوکت (socket) بیفتد، اندیشه ای بود که به وسیله نسخه توزیع شده Berkeley از سیستم عامل Unix مطرح شد، که اکنون به صورت مجازی در تمامی سیستم‌های عامل مورد پیشتیبانی قرار می‌گیرد و بناید رابطه‌های کاربری ویژه هر زبان است، که می‌تواند به کتابخانه socket در زبان برنامه‌نویسی Java و Python اشاره کرد. ما از زبان سی (C) و سیستم عامل لینوکس در تمام مثال‌هایی که در این سری از پست‌ها وجود دارد استفاده می‌کنیم، انتخاب لینوکس به این خاطر است که آن یک سیستم عامل منبع باز (Open source) است و زبان c را به این خاطر انتخاب می‌کنید که زبانی است که برای شبکه‌های داخلی بسیار به کار می‌رود. (زبان c همچنین این مزیت را دارند که بتواند جزئیات سطح پائین را نیز نشان دهد، که در درک موضوعاتی که از این به پس درباره آن‌ها صحبت می‌کنیم مفید باشد).

به خاطر توضیح رابط کاربری سوکت، این نکته مهم است که دو نکته مجزا از هم را در ذهن داشته باشید. هر کدام از پروتکل‌ها در خود مجموعه ای از سرویس‌ها را فراهم می‌آورد و رابط کاربری برنامه‌نویسی اپلیکیشن (API) در واقع یک سینتکس است که به وسیله این دسته از سرویس‌ها فراهم می‌آید تا بتوانند برخی از کارکردهای سیستم‌های کامپیوتری را فراخوان کرد. پیاده‌سازی که در اینجا انجام می‌شود، مسئول الگوکردن مجموعه ای از سیستم‌ها و آبجکت‌های غیرقابل حسی است که به وسیله رابط کاربری برنامه‌نویسی اپلیکیشن (API) در درون یک مجموعه انتزاعی از سرویس‌ها که آن‌ها نیز به وسیله پروتکل تعریف می‌شوند، پیاده‌سازی شده اند. اگر شما بتوانید یک رابط کاربری را به خوبی تعریف کنید، پس این امکان برای شما وجود دارد که بتوانید از سینتکس موجود برای فراخوان کردن سرویس‌های بسیاری از پروتکل‌ها استفاده کنید. این چنین عمومیت بخشی قطعا یکی از اهداف ایجاد رابط کاربری سوکت است، اگرچه تا پیاده‌سازی کامل و کارآمد آن راه زیادی باقیمانده است.

جای شگفتی نیست که در اینجا، شکل انتزاعی اصلی از رابط کاربری سوکت، خود سوکت است. یک راه خوب برای تفکر درباره سوکت آن است که آن را به صورت یک نقطه در نظر بگیریم که فرایندهای و پردازش‌های نرم‌افزاری از آن طریق به شبکه متصل می‌شوند. این رابط کاربری تعریف کننده عملیات‌هایی برای ساختن یک سوکت، محلق کردن یک سوکت به شبکه، ارسال و دریافت پیام‌ها از طریق سوکت، و بستن سوکت است. برای سادگی بحث، ما سعی می‌کنیم بحث خودمان را در اینجا محدود به نمایش دادن کارکرد سوکت با استفاده از پروتکل کنترل انتقال (TCP) کنیم.

چطور یک سوکت API بسازیم؟

اولین گام برای ساختن سوکت، در اینجا با استفاده از آنچه که در ادامه آمده است انجام می‌شود:

int socket(int domain, int type, int protocol);

دلیل اینکه این عملیات سه آرگومان را می‌گیرد آن است که رابط کاربری سوکت به صورت عمومی طراحی شده است تا بتواند به صورت کلی برای کار و پشتیبانی از هر سوئیت پروتکلی مناسب باشد. به ویژه در اینجا آرگومان Domain یک خانواده پروتکلی را معرفی می‌کند که می‌توان از آن برای ارسال پیام استفاده کرد: PF_INET در اینجا نشان دهنده خانواده اینترنت است، PF_UNIX نشان دهنده خانواده خطوط ارتباطی سیستم عامل Unix است و PF_PACKET نیز نشان دهنده دسترسی مستقیم به رابط کاربری شبکه است (که مسیر برگشتی پشته پروتکلی TCP/IP به حساب می‌آید). آرگومان type در اینجا به صورت معنایی نشان دهنده نوع ارتباطات است. SOCK_STREAM برای نشان دادن جریان بیتی به کار گرفته می‌شود. SOCK_DGRAM نیز یک روش جایگزین برای نشان دادن سرویس پیام محرو است، که می‌تواند به وسیله پروتکل دیتاگرام کاربر (UDP) فراهم آید. آرگومان protocol در اینجا معرفی کننده پروتکل ویژه ای است که می‌توان از آن در اینجا استفاده کرد. در مورد ما، آرگومان UNSPEC به خاطر ترکیب PF_INET و SOCK_STREAM که دلالت بر TCP دارند به کار گرفته می‌شود. در نهایت، مقدار برگشتی از طریق سوکت یک هندل برای سوکت‌های ساخته شده جدید است، به همین خاطر یک شناسه (Identifier) به وسیله هر کدام از ما ایجاد می‌شود، می‌تواند اشاره به سوکت در آینده داشته باشد. به همین خاطر، به عنوان یک آروگومان به عملیات‌های بعدی بر روی این سوکت داده می‌شود.

سوکت‌های نرم‌افزارها را قادر به ارتباط با دنیای بیرون می‌کنند

واقعا اهمیت رابط کاربری برنامه‌نویسی اپلیکیشن (API) سوکت جای اغراق ندارد. آن می‌توان نقطه ارتباطی میان نرم‌افزار‌هایی که در اینترنت فعال هستند باشد و هر آنچه که پیاده‌سازی شده است را با جزئیات در خود داشته باشد. در نتیجه این امر سوکت‌ها می‌توانند یک رابط کاربری پایدار و به خوبی طراحی شده را ایجاد کنند که به کمک آن نرم‌افزار‌های اینترنتی می‌توانند به صنعتی میلیون دلاری تبدیل شود. شروع این موضوع از فروتنانه از پارادایم کلاینت / سرور و برنامه‌های کاربردی ساده مانند ایمیل، انتقال فایل و وارد شدن از راه دور بود که هر شخصی این امکان را داشت که از طریق نرم‌افزارهای ابری که بر روی سیستم گوشی‌های همراه هوشمند خود، بتواند پشتیبانی‌های بی پایانی را دریافت کند.

در این بخش اساس کار با بازبینی سادگی برنامه‌ها طرف کاربر یک سوکت ایجاد می‌شد، و بنابراین آن می‌توانست پیام‌ها را با برنامه‌هایی که بر روی سرور قرار دارند تبادل کند، اما امروزه، اکوسیستمی قوی از نرم‌افزارها به وجود آمده اند که بر روی لایه API سوکت قرار گرفته اند. این لایه شامل تعداد زیادی از ابزارهایی است که مبتنی بر محیط و فضای ابری هستند و مانع کمتری را برای پیاده‌سازی نرم‌افزار مقیاس پذیر ایجاد می‌کنند. ما به تعامل میان محیط و فضای ابری و شبکه‌ها در هر کدام از پست‌های آینده بر خواهیم گشت و در بخش چشم اندازها در پست‌های بعدی بیشتر این موضوع را توضیح خواهیم داد.

گام بعدی در اینجا وابسته به این است که چطور شما یک سیستم کلاینت یا سرور را سازماندهی می‌کنید. در دستگاهی که به عنوان سرور می‌شناسیم، پردازش نرم‌افزارها به صورت غیرفعال انجام می‌شود، سرور می‌گوید که آن آماده قبول ارتباط است، اما واقعا هیچ تماسی را ایجاد نمی کند. سرور این فرخوان را با استفاده از سه عملیات انجام می‌دهد.

int bind(int socket, struct sockaddr *address, int addr_len);

int listen(int socket, int backlog);

int accept(int socket, struct sockaddr *address, int *addr_len)

 

در عملیات Bind یا اتصال، همانطور که از نام آن هم می‌توانید حد بزنید، یک سوکت جدید ایجاد می‌شود تا بتوان یک آدرس مشخص را به آن نسبت داد. این آدرس شبکه از همکار محلی یا سرور (Server) است. دقت کنید، هنگامی که در اینجا پروتکل‌های اینترنتی به کار گرفته می‌شود، آدرس می‌تواند یک ساختار داده باشد که شامل هم آدرس IP سرور و یک شمارت پورت TCP باشد. پورت‌ها برای پردازش‌های هویتی غیر مستقیم به کار برده می‌شوند. آن‌ها فرم دهنده یک کلید دموکس (demux key) هستند. شماره پورت در اینجا معمولا شماره‌های ویژه شناخته شده هستند که توسط سرور پیشنهاد می‌شوند: برای مثال، وب سرورها به صورت معمول ارتباط بر روی پورت 80 را قبول می‌کنند.

عملیات Listen و یا گوش دادن که بعد از این مرحله قرار می‌گیرد، مشخص می‌کن که چه تعداد اتصال می‌تواند در حالت انتظار برای یک سوکت تعریف شده باشند. در نهایت عملیات Accept یا پذیرش، قرار دارد که به صورت منفعل عملیات باز کردن سوکت‌ها را انجام می‌دهد. آن‌ها یک عملیات بلوک کردن (Blocking) است که تا زمانی که نرم‌افزار راه دور یک اتصال را ایجاد نکرده باشد، بازگشتی نخواهد داشت، و در زمانی که این عملیات کامل گردید، آن یک سوکت جدید را متناظر با این اتصال تازه تاسیس شده برمی گرداند، و آرگومان‌های آدرس حاوی آدرس‌های مشارکت کننده راه دور است. دقت کنید که در زمان پذیرش برگشتی‌ها یا پاسخ‌ها (Returns) سوکت اصلی به عنوان یک آرگومان هنوز وجود دارد و هنوز هم به شکل متناظر و منفعل باز است؛ آن در آینده برای فراخوان کردن پذیرش باز است.

در دستگاه سمت کاربر، نرم‌افزار کاربری عملکرد باز بودن را به صورت فعالانه اجرا می‌کند؛ به همین خاطر آن می‌گویند که آن درخواست ایجاد ارتباط را به وسیله یک عملیاد منفرد به شرح زیر می‌دهد:

int connect(int socket, struct sockaddr *address, int addr_len);

این عملیات تا زمانی که پروتکل کنترل انتقال (TCP) به صورت موفقیت آمیزی یک اتصال را ایجاد نکرده باشد، چیزی بر نمی گرداند و در زمانی که این اتصال برقرار شد، آن آزاد است که اقدام به ارسال داده‌ها کند. در این مورد، آدرس‌ها حاوی آدرس از مشارکت کنندگان راه دور هستند. به صورت عملی، طرف کاربر تنها می‌تواند آدرس مشارکت کنندگان راه دور را معرفی کند که باید از یک سیستم 40 کاراکتری برای نشان دادن اطلاعات محلی خودش استفاده کند. در حالی که یک سرور معمولا به پیام‌هایی که از پورت‌های شناخته شده خودش می‌رسد گوش می‌دهد، اما طرف کاربر در باره اینکه از کدام پورت برای ارتباط خودش استفاده کند، نگرانی ندارد؛ سیستم عامل‌ها به سادگی هر کدام از پورت‌هایی که مورد استفاده قرار نگرفته باشند را انتخاب می‌کنند.

در زمانی که اتصال بر قرار گردید، نرم‌افزار اقدام به پردازش فرخوان‌هایی می‌کند و از دو عملیات زیر برای ارسال و دریافت اطلاعات بهره می‌برد:

int send(int socket, char *message, int msg_len, int flags);

int recv(int socket, char *buffer, int buf_len, int flags);

اولین عملیات، عملیات ارسال (Send) است که پیام مشخصی را به سوکت تعریف شده ارسال می‌کند، در حالی که دومین عملیات، عملیات دریافت (Receives) پیام را از سوکت مشخصی که در بافر تعیین شده است دریافت میکند. هر دو عملیات د راینجا مجموعه ای از پرچم‌ها (Flags) را تنظیم می‌کند که مشخص کننده برخی از جزئیات تعریف شده در هر کدام از عملیات‌ها است.

No votes yet.
Please wait...

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.

منو اصلی

question