Anophel-آنوفل برنامه نویسی شبکه یا برنامه نویسی سوکت در پایتون چیست؟

برنامه نویسی شبکه یا برنامه نویسی سوکت در پایتون چیست؟

انتشار:
2

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

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

این همان چیزی است که سوکت ها را در برنامه های کاربردی سرویس کلاینت-سرور بلادرنگ (real-time) که به تبادل پیام فوری وابسته هستند یا با حجم عظیمی از داده ها کار می کنند، بسیار مفید می کند.

در این مقاله به اصول برنامه نویسی سوکت می پردازیم و راهنمای گام به گام ایجاد برنامه های کلاینت و سرور مبتنی بر سوکت با استفاده از پایتون را ارائه می دهیم.

مبانی شبکه

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


به همین ترتیب، شبکه های متعددی در فناوری اطلاعات وجود دارد. برجسته ترین و شناخته شده ترین آنها اینترنت است، شبکه جهانی شبکه هایی که دستگاه های بی شماری را به هم متصل می کند و احتمالاً در حال حاضر برای خواندن این مقاله از آن استفاده می کنید.


انواع شبکه ها

اینترنت شامل بسیاری از شبکه‌های بیشتر است که در مقیاس یا ویژگی‌های دیگر متفاوت هستند: برای مثال، شبکه‌های محلی (LAN)، که معمولاً رایانه‌هایی را که در مجاورت یکدیگر قرار دارند پیوند می‌دهند. ماشین‌های موجود در شرکت‌ها یا مؤسسات دیگر (بانک‌ها، دانشگاه‌ها و غیره) یا حتی دستگاه‌های خانگی شما که به یک روتر متصل هستند، چنین شبکه‌ای را تشکیل می‌دهند.

همچنین انواع بزرگتر یا کوچکتری از شبکه ها مانند PAN (شبکه منطقه شخصی) وجود دارد که می تواند به سادگی تلفن هوشمند شما از طریق بلوتوث به لپ تاپ متصل شود، MAN (شبکه منطقه شهری)، که می تواند دستگاه ها را در کل شهر به هم متصل کند، و WAN ها (منطقه وسیع). شبکه، که می تواند کل کشورها یا کل جهان را پوشش دهد. و بله، بزرگترین شبکه WAN خود اینترنت است.


ناگفته نماند که شبکه های کامپیوتری می توانند بسیار پیچیده باشند و از عناصر زیادی تشکیل شده باشند. یکی از ابتدایی ترین و حیاتی ترین پروتکل های ارتباطی است.


انواع پروتکل های ارتباطی شبکه

پروتکل های ارتباطی قوانین نحوه و فرمت ارسال و دریافت اطلاعات را مشخص می کنند. این پروتکل ها در یک سلسله مراتب جمع می شوند تا وظایف مختلف مربوط به ارتباطات شبکه را مدیریت کنند.


به عبارت دیگر، برخی از پروتکل‌ها نحوه دریافت، ارسال یا مسیریابی بسته‌ها توسط سخت‌افزار را مدیریت می‌کنند، در حالی که برخی دیگر سطح بالایی دارند و به عنوان مثال به ارتباطات سطح برنامه و غیره مربوط می‌شوند.


برخی از پروتکل های ارتباطی شبکه رایج و شناخته شده عبارتند از:


وای فای

نمونه‌ای از پروتکل لایه پیوند، به این معنی که بسیار نزدیک به سخت‌افزار قرار می‌گیرد و مسئول ارسال فیزیکی داده‌ها از یک دستگاه به دستگاه دیگر در یک محیط بی‌سیم است.


IP (پروتکل اینترنت)

IP یک پروتکل لایه شبکه است که عمدتاً مسئول مسیریابی بسته ها و آدرس دهی IP است.


TCP (پروتکل کنترل انتقال)

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


UDP (پروتکل دیتاگرام کاربر)

پروتکلی از همان مجموعه پروتکل TCP. تفاوت اصلی این است که UDP یک پروتکل بدون اتصال ساده تر، سریع تر، اما غیرقابل اعتماد است که هیچ گونه بررسی تحویل را انجام نمی دهد و از پارادایم "fire-and-forget" پیروی می کند. به عنوان TCP، UPD نیز در لایه انتقال قرار دارد.

HTTP (پروتکل انتقال ابرمتن)

یک پروتکل لایه کاربردی و رایج ترین پروتکل مورد استفاده برای ارتباط مرورگر به سرور در وب که به طور خاص برای سرویس دهی به وب سایت ها استفاده می شود. ناگفته نماند که این مقاله ای که هم اکنون می خوانید از طریق HTTP نیز ارائه شده است. پروتکل HTTP بر روی TCP ساخته می شود و اطلاعات مربوط به برنامه های کاربردی وب مانند هدرها را مدیریت و انتقال می دهد که برای انتقال ابرداده و کوکی ها، روش های مختلف HTTP (GET، POST، DELETE، UPDATE) و غیره استفاده می شود.


MQTT (انتقال تله متری صف پیام)

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


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


مفاهیم و اصطلاحات کلیدی

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


Packet: یک واحد استاندارد انتقال داده در یک شبکه کامپیوتری (می توان آن را به صورت محاوره ای با اصطلاح "پیام" مقایسه کرد).
نقطه پایانی (Endpoint): مقصدی که Packet ها به آنجا می رسند.
آدرس IP: یک شناسه عددی که به طور منحصر به فرد یک دستگاه را در شبکه شناسایی می کند. نمونه ای از آدرس IP این است: 192.168.0.0
پورت‌ها: یک شناسه عددی که به‌طور منحصربه‌فرد فرآیندی را که روی یک دستگاه اجرا می‌شود و ارتباطات شبکه خاصی را مدیریت می‌کند شناسایی می‌کند: برای مثال، وب‌سایت شما را از طریق HTTP ارائه می‌کند. در حالی که یک آدرس IP دستگاه را شناسایی می کند، یک پورت برنامه را شناسایی می کند (هر برنامه یک فرآیند یا شامل فرآیندهایی است). برخی از نمونه های معروف پورت عبارتند از: پورت 80، که به طور معمول توسط برنامه های کاربردی سرور برای مدیریت ترافیک HTTP استفاده می شود، و پورت 443 برای HTTPS (HTTP امن).
دروازه: نوع خاصی از گره شبکه (دستگاه) که به عنوان نقطه دسترسی از یک شبکه به شبکه دیگر عمل می کند. این شبکه ها حتی ممکن است از پروتکل های مختلفی استفاده کنند، بنابراین ممکن است برخی از ترجمه پروتکل ها توسط دروازه انجام شود. یک مثال از یک دروازه می تواند یک روتر باشد که یک شبکه محلی خانگی را به اینترنت متصل می کند.

سوکت چیست؟

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


هنگامی که یک سوکت در حالت گوش دادن یا اتصال است، همیشه به ترکیبی از یک آدرس IP به اضافه یک شماره پورت متصل است که میزبان (ماشین/دستگاه) و فرآیند را مشخص می کند.

نحوه عملکرد اتصالات سوکت

سوکت ها می توانند به اتصالات ورودی گوش دهند یا خودشان اتصالات خروجی را انجام دهند. هنگامی که یک اتصال برقرار می شود، سوکت شنود (سوکت سرور) علاوه بر این به IP و پورت سمت اتصال متصل می شود.


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


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


سوکت ها در زمینه شبکه ها

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


برنامه نویسی سوکت

هنگامی که ما در مورد برنامه نویسی سوکت صحبت می کنیم، اشیاء سوکت را در کد خود نمونه سازی می کنیم و عملیاتی را روی آنها انجام می دهیم (گوش دادن، اتصال، دریافت، ارسال و غیره). در این زمینه، سوکت ها به سادگی اشیاء خاصی هستند که ما در برنامه خود ایجاد می کنیم که روش های خاصی برای کار با اتصالات شبکه و ترافیک دارند.


این روش‌ها هسته سیستم عامل شما را می‌نامند، یا به طور خاص، پشته شبکه، که بخش خاصی از هسته مسئول مدیریت عملیات شبکه است.


سوکت ها و ارتباط کلاینت و سرور

اکنون، ذکر این نکته نیز مهم است که سوکت ها اغلب در زمینه ارتباط کلاینت-سرور ظاهر می شوند. ایده ساده است: سوکت ها به اتصالات مربوط می شوند. آنها کنترل کننده اتصال هستند. در وب، هر زمان که بخواهید برخی از داده ها را ارسال یا دریافت کنید، یک اتصال را راه اندازی می کنید (که از طریق رابطی به نام سوکت ها شروع می شود).


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


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


سوکت ها به عنوان پایه ای برای پروتکل های شبکه

این واقعیت که سوکت ها یک ستون فقرات را تشکیل می دهند همچنین به این معنی است که پروتکل های مختلفی در بالای آنها ساخته و استفاده می شود. موارد بسیار رایج UDP و TCP هستند که قبلاً به طور خلاصه در مورد آنها صحبت کرده ایم. سوکت هایی که از یکی از این پروتکل های انتقال استفاده می کنند، سوکت های UDP یا TCP نامیده می شوند.


سوکت IPC

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


خوبی سوکت های IPC این است که از هزینه های سربار زیادی برای ساخت بسته ها و حل مسیرهای ارسال داده ها جلوگیری می کنند. از آنجایی که در زمینه فرستنده و کلاینت IPC فرآیندهای محلی هستند، ارتباط از طریق سوکت های IPC معمولا تاخیر کمتری دارد.


سوکت های یونیکس

یک مثال خوب از سوکت‌های IPC، سوکت‌های یونیکس هستند که مانند همه چیز در یونیکس، فقط فایل‌های روی سیستم فایل هستند. آنها با آدرس IP و پورت شناسایی نمی شوند، بلکه توسط مسیر فایل در سیستم فایل شناسایی می شوند.

سوکت های شبکه به عنوان سوکت IPC

توجه داشته باشید که اگر سرور و کلاینت هر دو روی هاست لوکال هستند (یعنی دارای آدرس IP 127.0.0.1) باشند، می‌توانید به خوبی از سوکت‌های شبکه برای ارتباطات بین فرآیندی استفاده کنید.


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


کتابخانه سوکت پایتون

برای برنامه نویسی سوکت در پایتون، ما از کتابخانه رسمی داخلی سوکت پایتون متشکل از توابع، ثابت ها و کلاس هایی استفاده می کنیم که برای ایجاد، مدیریت و کار با سوکت ها استفاده می شوند. برخی از عملکردهای رایج این کتابخانه عبارتند از:


()socket: یک سوکت جدید ایجاد می کند.
()bind: سوکت را به یک آدرس و پورت خاص مرتبط می کند.
()listen: شروع به گوش دادن برای اتصالات ورودی در سوکت می کند.
()accept: اتصال از یک کلاینت را می پذیرد و یک سوکت جدید را برای ارتباط برمی گرداند.
()connect: اتصال به یک سرور راه دور را برقرار می کند.
()send: داده ها را از طریق سوکت ارسال می کند.
()recv: داده ها را از سوکت دریافت می کند.
()close: اتصال سوکت را می بندد.


نمونه سوکت پایتون

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


ملاحظات و محدودیت ها

با این حال، توجه داشته باشید که برای اهداف آموزشی، مثال ما ساده شده است، و برنامه ها به صورت محلی اجرا می شوند و از طریق شبکه واقعی صحبت نمی کنند - ما از یک آدرس لوکال هاست حلقه بک برای اتصال کلاینت به سرور استفاده خواهیم کرد.


این بدان معناست که هم کلاینت و هم سرور بر روی یک ماشین اجرا می‌شوند و کلاینت با همان ماشینی که روی آن در حال اجرا است، اتصال برقرار می‌کند، البته به فرآیند متفاوتی که نشان دهنده سرور است.

در حال اجرا بر روی ماشین های مختلف
از طرف دیگر، می توانید برنامه های خود را در دو دستگاه مختلف داشته باشید و هر دو را به یک روتر Wi-Fi متصل کنید، که یک شبکه محلی را تشکیل می دهد. سپس کلاینت در حال اجرا بر روی یک دستگاه می تواند به سروری که روی دستگاه دیگری کار می کند متصل شود.


با این حال، در این مورد، باید آدرس های IP را که روتر شما به دستگاه های شما اختصاص داده است بدانید و به جای آدرس IP Loopback Loopback (127.0.0.1) از آنها استفاده کنید (برای مشاهده آدرس های IP، از دستور ترمینال ifconfig برای سیستم های یونیکس مانند استفاده کنید. یا ipconfig - برای ویندوز). پس از به دست آوردن آدرس های IP برنامه های خود، می توانید آنها را در کد مطابق با آن تغییر دهید و مثال همچنان کار خواهد کرد.


به هر حال ما با مثال خود شروع می کنیم. اگر می خواهید دنبال کنید، البته باید پایتون را نصب کنید.


ایجاد سوکت سرور در پایتون

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


بنابراین، مراحل زیر را دنبال کنید:

ایجاد فایل پایتون با مقداری boilerplate
 

یک فایل با نام server.py ایجاد کنید
ماژول سوکت را در اسکریپت پایتون خود وارد کنید.

import socket

تابعی به نام run_server اضافه کنید. ما بیشتر کد خود را در آنجا اضافه خواهیم کرد. هنگامی که کد خود را به تابع اضافه می کنید، فراموش نکنید که آن را به درستی تورفتگی کنید:

def run_server():
    # your code will go here

نمونه آبجکت سوکت

در مرحله بعد، در run_server، یک شی سوکت با استفاده از تابع ()socket.socket ایجاد کنید.


آرگومان اول (socket.AF_INET) خانواده آدرس IP را برای IPv4 مشخص می کند (گزینه های دیگر عبارتند از: AF_INET6 برای خانواده IPv6 و AF_UNIX برای سوکت های Unix)


آرگومان دوم (socket.SOCK_STREAM) نشان می دهد که ما از یک سوکت TCP استفاده می کنیم.


در صورت استفاده از TCP، سیستم عامل یک ارتباط قابل اعتماد با تحویل به ترتیب داده، کشف خطا و ارسال مجدد و کنترل جریان ایجاد می کند. شما مجبور نخواهید بود به اجرای تمام آن جزئیات فکر کنید.


همچنین گزینه ای برای تعیین سوکت UDP وجود دارد: socket.SOCK_DGRAM. این یک سوکت ایجاد می کند که تمام ویژگی های UDP را در زیر هود اجرا می کند.


اگر می‌خواهید سطح پایین‌تری از آن داشته باشید و پروتکل لایه انتقال خود را در بالای پروتکل لایه شبکه TCP/IP که توسط سوکت‌ها استفاده می‌شود بسازید، می‌توانید از مقدار socket.RAW_SOCKET برای آرگومان دوم استفاده کنید. در این حالت، سیستم عامل هیچ ویژگی پروتکل سطح بالاتری را برای شما مدیریت نخواهد کرد و در صورت نیاز باید تمام هدرها، تأیید اتصال و قابلیت های ارسال مجدد را خودتان پیاده سازی کنید. مقادیر دیگری نیز وجود دارد که می توانید در مستندات درباره آنها بخوانید.

# create a socket object
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

اتصال سوکت سرور به آدرس IP و پورت

نام میزبان یا IP و پورت سرور را برای نشان دادن آدرسی که سرور از آن قابل دسترسی است و جایی که برای اتصالات ورودی گوش می دهد، تعریف کنید. در این مثال، سرور در حال گوش دادن به ماشین محلی است - این توسط متغیر server_ip که روی 127.0.0.1 تنظیم شده است (که به آن localhost نیز گفته می شود) تعریف شده است.

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

server_ip = "127.0.0.1"
    port = 8000

سوکت را با اتصال به آدرس IP و پورتی که قبلاً تعریف کرده ایم، برای دریافت اتصالات آماده کنید.

# bind the socket to a specific address and port
    server.bind((server_ip, port))

گوش دادن برای اتصالات ورودی

با استفاده از عملکرد گوش دادن، وضعیت گوش دادن را در سوکت سرور تنظیم کنید تا بتوانید اتصالات کلاینت ورودی را دریافت کنید.

این تابع آرگومانی به نام backlog را می پذیرد که حداکثر تعداد اتصالات پذیرفته نشده در صف را مشخص می کند. در این مثال از مقدار 0 برای این آرگومان استفاده می کنیم. این بدان معنی است که تنها یک کلاینت می تواند با سرور تعامل داشته باشد. تلاش برای اتصال هر کلاینت در حالی که سرور با کلاینت دیگری کار می کند، رد خواهد شد.

اگر مقداری بزرگتر از 0 را مشخص کنید، مثلاً 1، به سیستم عامل می گوید که چه تعداد کلاینت را می توان قبل از فراخوانی متد پذیرش در صف قرار داد.

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

اگر آرگومان بک لاگ را حذف کنید، روی پیش فرض سیستم شما تنظیم می شود (در یونیکس، معمولاً می توانید این پیش فرض را در فایل proc/sys/net/core/somaxconn/ مشاهده کنید).

# listen for incoming connections
    server.listen(0)
    print(f"Listening on {server_ip}:{port}")

پذیرش اتصالات ورودی

سپس، منتظر بمانید و اتصالات کلاینت ورودی را بپذیرید. متد پذیرش رشته اجرا را تا زمانی که یک کلاینت متصل شود متوقف می کند. سپس یک جفت تاپلی (conn, address) را برمی‌گرداند، که در آن آدرس یک تاپلی از آدرس IP و پورت کلاینت است، و conn یک شی سوکت جدید است که یک اتصال را با کلاینت به اشتراک می‌گذارد و می‌تواند برای ارتباط با آن استفاده شود.

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

# accept incoming connections
    client_socket, client_address = server.accept()
    print(f"Accepted connection from {client_address[0]}:{client_address[1]}")

ایجاد حلقه ارتباطی

به محض برقراری ارتباط با کلاینت (پس از فراخوانی متد پذیرش)، یک حلقه بی نهایت برای برقراری ارتباط راه اندازی می کنیم. در این حلقه یک فراخوانی به متد recv شی client_socket انجام می دهیم. این روش تعداد مشخص شده بایت را از کلاینت دریافت می کند - در مورد ما 1024.

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

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

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

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

# receive data from the client
    while True:
        request = client_socket.recv(1024)
        request = request.decode("utf-8") # convert bytes to string
        
        # if we receive "close" from the client, then we break
        # out of the loop and close the conneciton
        if request.lower() == "close":
            # send response to the client which acknowledges that the
            # connection should be closed and break out of the loop
            client_socket.send("closed".encode("utf-8"))
            break

        print(f"Received: {request}")

ارسال پاسخ به کلاینت

اکنون باید پاسخ عادی سرور به کلاینت را کنترل کنیم (یعنی زمانی که کلاینت نمی خواهد اتصال را ببندد). در داخل حلقه while، درست پس از چاپ (f"Received: {request}")، خطوط زیر را اضافه کنید، که یک رشته پاسخ (در مورد ما "پذیرفته شده") به بایت تبدیل می شود و آن را برای کلاینت ارسال می کند. به این ترتیب هر زمان که سرور پیامی از کلاینت دریافت می کند که "close" نیست، رشته "پذیرفته شده" را در پاسخ ارسال می کند:

response = "accepted".encode("utf-8") # convert string to bytes
# convert and send accept response to the client
client_socket.send(response)

آزاد کردن منابع

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

در حال حاضر، خطوط زیر را بعد از حلقه while بی نهایت اضافه کنید:

# close connection socket with the client
    client_socket.close()
    print("Connection to client closed")
    # close server socket
    server.close()

فراموش نکنید که تابع run_server را در انتهای فایل server.py خود فراخوانی کنید. به سادگی از خط کد زیر استفاده کنید:

run_server()

ایجاد سوکت کلاینت در پایتون

پس از راه اندازی سرور خود، مرحله بعدی راه اندازی یک کلاینت است که به سرور شما متصل شده و درخواست ها را ارسال می کند. بنابراین، اجازه دهید با مراحل زیر شروع کنیم:

ایجاد فایل پایتون با مقداری boilerplate
یک فایل جدید با نام client.py ایجاد کنید


وارد کردن کتابخانه سوکت:

import socket

تابع run_client را تعریف کنید که همه کدهای خود را در آن قرار می دهیم:

def run_client():
    # your code will go here

نمونه آبجکت سوکت

سپس، از تابع ()socket.socket برای ایجاد یک آبجکت سوکت TCP استفاده کنید که به عنوان نقطه تماس کلاینت با سرور عمل می کند.

# create a socket object
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

اتصال به سوکت سرور

آدرس IP و پورت سرور را مشخص کنید تا بتوانید به آن متصل شوید. اینها باید با آدرس IP و پورتی که قبلاً در server.py تنظیم کرده‌اید مطابقت داشته باشند.

    server_ip = "127.0.0.1"  # replace with the server's IP address
    server_port = 8000  # replace with the server's port number

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

    # establish connection with server
    client.connect((server_ip, server_port))

ایجاد حلقه ارتباطی

پس از برقراری ارتباط، یک حلقه ارتباطی بی نهایت برای ارسال چندین پیام به سرور راه اندازی می کنیم. ما ورودی را از کاربر با استفاده از تابع ورودی داخلی پایتون دریافت می کنیم، سپس آن را به بایت کدگذاری می کنیم و حداکثر 1024 بایت را برش می دهیم. پس از آن با استفاده از client.send پیام را به سرور ارسال می کنیم.

   while True:
        # input message and send it to the server
        msg = input("Enter message: ")
        client.send(msg.encode("utf-8")[:1024])

رسیدگی به پاسخ سرور

هنگامی که سرور پیامی را از کلاینت دریافت می کند، به آن پاسخ می دهد. اکنون در کد کلاینت خود می خواهیم پاسخ سرور را دریافت کنیم. برای آن، در حلقه ارتباطی، از روش recv برای خواندن حداکثر 1024 بایت استفاده می کنیم. سپس پاسخ از بایت ها را با استفاده از رمزگشایی به رشته تبدیل می کنیم و سپس بررسی می کنیم که آیا برابر با مقدار "closed" است یا خیر. اگر اینطور باشد، از حلقه خارج می شویم که همانطور که بعداً می بینیم، اتصال کلاینت را قطع می کند. در غیر این صورت، ما پاسخ سرور را در کنسول چاپ می کنیم.

       # receive message from the server
        response = client.recv(1024)
        response = response.decode("utf-8")

        # if server sent us "closed" in the payload, we break out of the loop and close our socket
        if response.lower() == "closed":
            break

        print(f"Received: {response}")

آزاد کردن منابع

در نهایت پس از حلقه while، اتصال سوکت کلاینت را با استفاده از روش close ببندید. این تضمین می کند که منابع به درستی آزاد شده و اتصال قطع می شود (یعنی زمانی که پیام "closed" را دریافت می کنیم و از حلقه while خارج می شویم).

   # close client socket (connection to the server)
    client.close()
    print("Connection to server closed")

باز هم فراموش نکنید که تابع run_client را که در بالا پیاده سازی کردیم در انتهای فایل به صورت زیر فراخوانی کنید:

run_client()

کلاینت و سرور خود را تست کنید

برای آزمایش اجرای سرور و کلاینت که در بالا نوشتیم، موارد زیر را انجام دهید:

دو پنجره ترمینال را به طور همزمان باز کنید.
در یک پنجره ترمینال، به دایرکتوری که فایل server.py در آن قرار دارد بروید و دستور زیر را برای راه اندازی سرور اجرا کنید:

   python server.py

این سوکت سرور را به آدرس لوکال هاست (127.0.0.1) در پورت 8000 متصل می کند و شروع به گوش دادن برای اتصالات ورودی می کند.

در ترمینال دیگر، به دایرکتوری که فایل client.py در آن قرار دارد بروید و دستور زیر را برای راه اندازی کلاینت اجرا کنید:

   python client.py

با این کار ورودی کاربر درخواست می شود. سپس می توانید پیام خود را تایپ کرده و Enter را فشار دهید. با این کار ورودی شما به سرور منتقل می شود و در پنجره ترمینال آن نمایش داده می شود. سرور پاسخ خود را برای کلاینت ارسال می کند و کلاینت مجدداً از شما ورودی می خواهد. این کار تا زمانی ادامه می یابد که رشته "close" را به سرور ارسال کنید.

کاربردهای برنامه نویسی سوکت در علم داده

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


جمع آوری داده ها به صورت rea;-time

سوکت ها به طور گسترده برای جمع آوری داده های بلادرنگ از منابع مختلف برای پردازش بیشتر، ارسال به پایگاه داده یا pipeline تجزیه و تحلیل و غیره استفاده می شوند. به عنوان مثال، یک سوکت می تواند برای دریافت فوری داده ها از یک سیستم مالی یا API رسانه اجتماعی برای کارهای بعدی استفاده شود. پردازش توسط دانشمندان داده


محاسبات توزیع شده

دانشمندان داده ممکن است از اتصال سوکت برای توزیع پردازش و محاسبات مجموعه داده های عظیم در چندین ماشین استفاده کنند. برنامه نویسی سوکت معمولاً در Apache Spark و سایر چارچوب های محاسباتی توزیع شده برای ارتباط بین گره ها استفاده می شود.


استقرار مدل

هنگام ارائه مدل‌های یادگیری ماشین به کاربران، می‌توان از برنامه‌نویسی سوکت استفاده کرد که امکان تحویل فوری پیش‌بینی‌ها و پیشنهادات را فراهم می‌کند. به منظور تسهیل تصمیم‌گیری بلادرنگ، دانشمندان داده ممکن است از برنامه‌های کاربردی سرور مبتنی بر سوکت استفاده کنند که مقادیر زیادی داده را دریافت می‌کنند، آن‌ها را با استفاده از مدل‌های آموزش‌دیده برای ارائه پیش‌بینی‌ها پردازش می‌کنند و سپس به سرعت یافته‌ها را به کلاینت برمی‌گردانند.


ارتباطات بین فرآیندی (IPC)

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


همکاری و ارتباط

برنامه نویسی سوکت امکان ارتباط و همکاری بلادرنگ بین دانشمندان داده را فراهم می کند. به منظور تسهیل همکاری موثر و به اشتراک گذاری دانش، از برنامه های چت مبتنی بر سوکت یا پلت فرم های تجزیه و تحلیل داده های مشترک استفاده می شود.


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

نتیجه

سوکت ها بخشی جدایی ناپذیر از همه برنامه های شبکه هستند. در این مقاله به برنامه نویسی سوکت در پایتون پرداخته ایم. در اینجا نکات کلیدی برای یادآوری وجود دارد:


سوکت ها رابط هایی هستند که مدیریت اتصال را انتزاعی می کنند.
سوکت ها ارتباط بین فرآیندهای مختلف (معمولاً یک کلاینت و یک سرور) را به صورت محلی یا از طریق شبکه امکان پذیر می کنند.
در پایتون، کار با سوکت ها از طریق کتابخانه سوکت انجام می شود که در بین بقیه، یک شی سوکت را با روش های مختلفی مانند recv، send، listen، close ارائه می دهد.
برنامه نویسی سوکت کاربردهای مختلفی دارد که در علم داده مفید است، از جمله جمع آوری داده ها، ارتباطات بین فرآیندی و محاسبات توزیع شده.
چالش‌های برنامه‌نویسی سوکت شامل مدیریت اتصال، یکپارچگی داده، مقیاس‌پذیری، مدیریت خطا، امنیت و قابلیت نگهداری کد است.


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


با این حال، برنامه نویسی سوکت یک تکنیک بسیار سطح پایین است که استفاده از آن دشوار است زیرا مهندسان برنامه باید هر جزئیات کوچکی از ارتباطات برنامه را در نظر بگیرند.


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

#socket#python#network#سوکت#سوکت_نویسی#شبکه#پایتون
نظرات ارزشمند شما :

در حال دریافت...

مقاله های مشابه

در حال دریافت...